216 lines
7.6 KiB
JavaScript
216 lines
7.6 KiB
JavaScript
import { findPropertyPython } from "./configProperties.js"
|
|
import { DtButtonsTypeHandler } from './lora.js'
|
|
import { DtModelTypeHandler } from "./models.js"
|
|
import { checkVersion } from './upgrade.js'
|
|
import { setCallback, updateProto } from "./util.js"
|
|
|
|
|
|
export const nodePackVersion = "1.6.2"
|
|
let previewMethod = undefined
|
|
|
|
// this holds the node definition from python
|
|
let dtSamplerNodeData = null
|
|
|
|
/** @type {import("@comfyorg/comfyui-frontend-types").ComfyExtension} */
|
|
export default {
|
|
name: "core",
|
|
|
|
getCustomWidgets(app) {
|
|
return {
|
|
DT_MODEL: DtModelTypeHandler,
|
|
"DT_BUTTONS": DtButtonsTypeHandler
|
|
}
|
|
},
|
|
|
|
beforeConfigureGraph(graph) {
|
|
for (const node of graph.nodes) {
|
|
if (node.type === "DrawThingsPositive" || node.type === "DrawThingsNegative") {
|
|
node.type = "DrawThingsPrompt"
|
|
node.properties['Node name for S&R'] = "DrawThingsPrompt"
|
|
delete node.properties.ver
|
|
node.widgets_values.unshift("...")
|
|
}
|
|
}
|
|
},
|
|
|
|
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
|
if (nodeType.comfyClass === "DrawThingsSampler") {
|
|
updateProto(nodeType, samplerProto)
|
|
dtSamplerNodeData = nodeData
|
|
}
|
|
},
|
|
|
|
// beforeConfigureGraph: function (graph) {
|
|
// const samplerNodes = graph.nodes.filter(n => n.type === "DrawThingsSampler")
|
|
// if (samplerNodes.some(n => n.nodePackVersion !== nodePackVersion)) {
|
|
// console.log("Nodes in workflow are from different version of ComfyUI-DrawThings-gRPC")
|
|
// }
|
|
// },
|
|
|
|
async setup(app) {
|
|
// query the api for the preview setting
|
|
await updatePreviewSetting()
|
|
|
|
// listen to the manager ui to update preview setting if necessary
|
|
const closeHandler = async () => {
|
|
await updatePreviewSetting()
|
|
}
|
|
setTimeout(() => document.querySelector('button[title="ComfyUI Manager"]').addEventListener("click", async () => {
|
|
document.getElementById('cm-close-button')?.addEventListener("click", closeHandler, { once: true })
|
|
}), 3000)
|
|
|
|
// if the prompt is cancelled, send a signal to the server to cancel the grpc request
|
|
setCallback(app.api, "interrupt", async (e) => {
|
|
if (app.graph.nodes.some(n => n.type === "DrawThingsSampler")) {
|
|
await app.api.fetchApi(`/dt_grpc/interrupt`, {
|
|
method: "POST",
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
/** @type {import("@comfyorg/litegraph").LGraphNode} */
|
|
const samplerProto = {
|
|
async onNodeCreated() {
|
|
const inputPos = this.inputs.find((inputPos) => inputPos.name == "positive")
|
|
const inputNeg = this.inputs.find((inputNeg) => inputNeg.name == "negative")
|
|
inputPos.color_on =
|
|
inputPos.color_off =
|
|
inputNeg.color_on =
|
|
inputNeg.color_off =
|
|
app.canvas.default_connection_color_byType["CONDITIONING"]
|
|
app.canvas.default_connection_color_byType["DT_LORA"] = app.canvas.default_connection_color_byType["MODEL"]
|
|
app.canvas.default_connection_color_byType["DT_CNET"] =
|
|
app.canvas.default_connection_color_byType["CONTROL_NET"]
|
|
|
|
setTimeout(() => checkVersion(nodePackVersion), 2000)
|
|
},
|
|
|
|
onMouseDown(e, pos, canvas) {
|
|
// this exists for easier debugging in devtools
|
|
console.debug("Click!", this)
|
|
},
|
|
|
|
onSerialize(serialised) {
|
|
serialised.nodePackVersion = nodePackVersion
|
|
serialised.widget_values_keyed = Object.fromEntries(this.widgets.map(w => ([w.name, w.value])))
|
|
},
|
|
|
|
onConfigure(serialised) {
|
|
// at this point, the node should already be loaded with values from the values array
|
|
|
|
// if there is keyed data, apply that
|
|
if (serialised.widget_values_keyed) {
|
|
for (const [name, value] of Object.entries(serialised.widget_values_keyed)) {
|
|
const widget = this.widgets.find((w) => w.name === name)
|
|
if (widget) widget.value = value
|
|
}
|
|
}
|
|
|
|
// check each widget value
|
|
const corrections = []
|
|
for (const w of this.widgets) {
|
|
const prop = findPropertyPython(w.name)
|
|
if (!prop) {
|
|
continue
|
|
}
|
|
const coerced = prop.coerce(w.value)
|
|
if (coerced !== w.value) {
|
|
corrections.push({ name: w.name, value: w.value, coerced })
|
|
w.value = coerced
|
|
}
|
|
}
|
|
|
|
if (corrections.length) {
|
|
const message = 'The Draw Things Sampler node contained invalid values - they have been corrected:'
|
|
const list = corrections.map((c) => `${c.name}: ${c.value} -> ${c.coerced}`)
|
|
const detail = message + "\n\n" + list.join("\n")
|
|
|
|
app.extensionManager.toast.add({
|
|
severity: "info",
|
|
summary: "Draw Things gRPC",
|
|
detail,
|
|
life: 8000
|
|
})
|
|
}
|
|
|
|
delete this.widget_values_keyed
|
|
|
|
this.updateDynamicWidgets?.()
|
|
},
|
|
|
|
getExtraMenuOptions(canvas, options) {
|
|
const keepNodeShrunk = app.extensionManager.setting.get("drawthings.node.keep_shrunk")
|
|
options.push(
|
|
null,
|
|
{
|
|
content: "Paste Draw Things config",
|
|
callback: () => {
|
|
navigator.clipboard.readText().then(async (text) => {
|
|
try {
|
|
const config = JSON.parse(text)
|
|
|
|
for (const w of this.widgets) {
|
|
const prop = findPropertyPython(w.name)
|
|
if (!prop)
|
|
continue
|
|
await prop.import(w.name, config[prop.json], w, this, config)
|
|
}
|
|
|
|
this.updateDynamicWidgets?.()
|
|
} catch (e) {
|
|
alert("Failed to parse Draw Things config from clipboard\n\n" + e)
|
|
console.warn(e)
|
|
}
|
|
})
|
|
},
|
|
},
|
|
{
|
|
content: "Copy Draw Things config",
|
|
callback: () => {
|
|
const config = {}
|
|
for (const w of this.widgets) {
|
|
const prop = findPropertyPython(w.name)
|
|
if (!prop)
|
|
continue
|
|
prop.export(w, this, config)
|
|
}
|
|
config.loras = []
|
|
config.control = []
|
|
navigator.clipboard.writeText(JSON.stringify(config))
|
|
},
|
|
},
|
|
{
|
|
content: (keepNodeShrunk ? "✓ " : "") + "Keep node shrunk when widgets change",
|
|
callback: async () => {
|
|
try {
|
|
await app.extensionManager.setting.set("drawthings.node.keep_shrunk", !keepNodeShrunk)
|
|
} catch (error) {
|
|
console.error(`Error changing setting: ${error}`)
|
|
}
|
|
},
|
|
},
|
|
null
|
|
)
|
|
},
|
|
}
|
|
|
|
|
|
async function updatePreviewSetting() {
|
|
const api = window.comfyAPI.api.api
|
|
|
|
const res = await api.fetchApi('/manager/preview_method')
|
|
previewMethod = await res.text()
|
|
|
|
const body = new FormData()
|
|
body.append("preview", previewMethod)
|
|
|
|
await api.fetchApi(`/dt_grpc/preview`, {
|
|
method: "POST",
|
|
body,
|
|
})
|
|
}
|
|
|
|
/** @import { LGraphCanvas, LGraphNode, WidgetCallback, IWidget } from "litegraph.js"; */
|