|
import { app } from "../../../scripts/app.js"; |
|
import { $el, ComfyDialog } from "../../../scripts/ui.js"; |
|
|
|
|
|
|
|
const id = "pysssss.WidgetDefaults"; |
|
const nodeDataKey = Symbol(); |
|
|
|
app.registerExtension({ |
|
name: id, |
|
beforeRegisterNodeDef(nodeType, nodeData) { |
|
nodeType[nodeDataKey] = nodeData; |
|
}, |
|
setup() { |
|
let defaults; |
|
let setting; |
|
|
|
const applyDefaults = (defaults) => { |
|
for (const node of Object.values(LiteGraph.registered_node_types)) { |
|
const nodeData = node[nodeDataKey]; |
|
if (!nodeData) continue; |
|
const nodeDefaults = defaults[node.type]; |
|
if (!nodeDefaults) continue; |
|
const inputs = { ...(nodeData.input?.required || {}), ...(nodeData.input?.optional || {}) }; |
|
|
|
for (const w in nodeDefaults) { |
|
const widgetDef = inputs[w]; |
|
if (widgetDef) { |
|
let v = nodeDefaults[w]; |
|
if (widgetDef[0] === "INT" || widgetDef[0] === "FLOAT") { |
|
v = +v; |
|
} |
|
if (widgetDef[1]) { |
|
widgetDef[1].default = v; |
|
} else { |
|
widgetDef[1] = { default: v }; |
|
} |
|
} |
|
} |
|
} |
|
}; |
|
|
|
const getDefaults = () => { |
|
let items; |
|
try { |
|
items = JSON.parse(setting.value); |
|
items = items.reduce((p, n) => { |
|
if (!p[n.node]) p[n.node] = {}; |
|
p[n.node][n.widget] = n.value; |
|
return p; |
|
}, {}); |
|
} catch (error) {} |
|
if (!items) { |
|
items = {}; |
|
} |
|
applyDefaults(items); |
|
return items; |
|
}; |
|
|
|
const onNodeAdded = app.graph.onNodeAdded; |
|
app.graph.onNodeAdded = function (node) { |
|
onNodeAdded?.apply?.(this, arguments); |
|
|
|
|
|
const nodeDefaults = defaults[node.constructor.type]; |
|
if (!nodeDefaults) return; |
|
|
|
|
|
const stack = new Error().stack; |
|
if (stack.includes("pasteFromClipboard") || stack.includes("loadGraphData")) { |
|
return; |
|
} |
|
|
|
for (const k in nodeDefaults) { |
|
if (k.startsWith("property.")) { |
|
const name = k.substring(9); |
|
let v = nodeDefaults[k]; |
|
|
|
if (name in node || ["color", "bgcolor", "title"].includes(name)) { |
|
node[name] = v; |
|
} else { |
|
|
|
if (!node.properties) node.properties = {}; |
|
if (typeof node.properties[name] === "number") v = +v; |
|
else if (typeof node.properties[name] === "boolean") v = v === "true"; |
|
else if (v === "true") v = true; |
|
|
|
node.properties[name] = v; |
|
} |
|
} |
|
} |
|
}; |
|
|
|
class WidgetDefaultsDialog extends ComfyDialog { |
|
constructor() { |
|
super(); |
|
this.element.classList.add("comfy-manage-templates"); |
|
this.grid = $el( |
|
"div", |
|
{ |
|
style: { |
|
display: "grid", |
|
gridTemplateColumns: "1fr auto auto auto", |
|
gap: "5px", |
|
}, |
|
className: "pysssss-widget-defaults", |
|
}, |
|
[ |
|
$el("label", { |
|
textContent: "Node Class", |
|
}), |
|
$el("label", { |
|
textContent: "Widget Name", |
|
}), |
|
$el("label", { |
|
textContent: "Default Value", |
|
}), |
|
$el("label"), |
|
(this.rows = $el("div", { |
|
style: { |
|
display: "contents", |
|
}, |
|
})), |
|
] |
|
); |
|
} |
|
|
|
createButtons() { |
|
const btns = super.createButtons(); |
|
btns[0].textContent = "Cancel"; |
|
btns.unshift( |
|
$el("button", { |
|
type: "button", |
|
textContent: "Add New", |
|
onclick: () => this.addRow(), |
|
}), |
|
$el("button", { |
|
type: "button", |
|
textContent: "Save", |
|
onclick: () => this.save(), |
|
}) |
|
); |
|
return btns; |
|
} |
|
|
|
addRow(node = "", widget = "", value = "") { |
|
let nameInput; |
|
this.rows.append( |
|
$el( |
|
"div", |
|
{ |
|
style: { |
|
display: "contents", |
|
}, |
|
className: "pysssss-widget-defaults-row", |
|
}, |
|
[ |
|
$el("input", { |
|
placeholder: "e.g. CheckpointLoaderSimple", |
|
value: node, |
|
}), |
|
$el("input", { |
|
placeholder: "e.g. ckpt_name", |
|
value: widget, |
|
$: (el) => (nameInput = el), |
|
}), |
|
$el("input", { |
|
placeholder: "e.g. myBestModel.safetensors", |
|
value, |
|
}), |
|
$el("button", { |
|
textContent: "Delete", |
|
style: { |
|
fontSize: "12px", |
|
color: "red", |
|
fontWeight: "normal", |
|
}, |
|
onclick: (e) => { |
|
nameInput.value = ""; |
|
e.target.parentElement.style.display = "none"; |
|
}, |
|
}), |
|
] |
|
) |
|
); |
|
} |
|
|
|
save() { |
|
const rows = this.rows.children; |
|
const items = []; |
|
|
|
for (const row of rows) { |
|
const inputs = row.querySelectorAll("input"); |
|
const node = inputs[0].value.trim(); |
|
const widget = inputs[1].value.trim(); |
|
const value = inputs[2].value; |
|
if (node && widget) { |
|
items.push({ node, widget, value }); |
|
} |
|
} |
|
|
|
setting.value = JSON.stringify(items); |
|
defaults = getDefaults(); |
|
|
|
this.close(); |
|
} |
|
|
|
show() { |
|
this.rows.replaceChildren(); |
|
for (const nodeName in defaults) { |
|
const node = defaults[nodeName]; |
|
for (const widgetName in node) { |
|
this.addRow(nodeName, widgetName, node[widgetName]); |
|
} |
|
} |
|
|
|
this.addRow(); |
|
super.show(this.grid); |
|
} |
|
} |
|
|
|
setting = app.ui.settings.addSetting({ |
|
id, |
|
name: "๐ Widget Defaults", |
|
type: () => { |
|
return $el("tr", [ |
|
$el("td", [ |
|
$el("label", { |
|
for: id.replaceAll(".", "-"), |
|
textContent: "๐ Widget & Property Defaults:", |
|
}), |
|
]), |
|
$el("td", [ |
|
$el("button", { |
|
textContent: "Manage", |
|
onclick: () => { |
|
app.ui.settings.element.close(); |
|
const dialog = new WidgetDefaultsDialog(); |
|
dialog.show(); |
|
}, |
|
style: { |
|
fontSize: "14px", |
|
}, |
|
}), |
|
]), |
|
]); |
|
}, |
|
}); |
|
defaults = getDefaults(); |
|
}, |
|
}); |
|
|