Back to Python nodes with preview + text input

- SimpleSet/Get use text input (type any name)
- Preview shows on node after execution
- SimpleGet has trigger input for execution order
- SimpleList shows all variables
- SimpleClear clears all

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
jessesep
2025-12-05 02:30:24 +01:00
co-authored by Claude
parent 1e8bd05938
commit 61a2c58a3a
2 changed files with 146 additions and 104 deletions
+37 -94
View File
@@ -1,120 +1,63 @@
import { app } from "/scripts/app.js";
import { ComfyWidgets } from "/scripts/widgets.js";
// Override Python nodes with virtual node behavior
// Display text on nodes when they execute
app.registerExtension({
name: "SimpleVariables",
beforeRegisterNodeDef(nodeType, nodeData, app) {
if (nodeData.name === "SimpleSet") {
// Make it a virtual node - passes data through without Python execution
const onNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = function() {
if (onNodeCreated) onNodeCreated.apply(this, arguments);
beforeRegisterNodeDef(nodeType, nodeData, appInstance) {
if (["SimpleSet", "SimpleGet", "SimpleList", "SimpleClear"].includes(nodeData.name)) {
const node = this;
this.isVirtualNode = true;
const onExecuted = nodeType.prototype.onExecuted;
nodeType.prototype.onExecuted = function(message) {
if (onExecuted) onExecuted.apply(this, arguments);
// Update title when name changes
const nameWidget = this.widgets?.find(w => w.name === "name");
if (nameWidget) {
const origCallback = nameWidget.callback;
nameWidget.callback = function(value) {
if (origCallback) origCallback.apply(this, arguments);
node.title = value ? `Set: ${value}` : "SimpleSet";
};
}
if (message?.text) {
// Find or create display widget
let widget = this.widgets?.find(w => w.name === "_display");
// Update slot types when connection changes
this.onConnectionsChange = function(slotType, slot, isConnect, linkInfo) {
if (slotType === 1 && node.inputs?.[0]) {
if (isConnect && node.graph) {
const link = node.graph.links?.[node.inputs[0].link];
if (link) {
const originNode = node.graph._nodes_by_id[link.origin_id];
if (originNode?.outputs?.[link.origin_slot]) {
const type = originNode.outputs[link.origin_slot].type;
node.inputs[0].type = type;
node.inputs[0].name = type;
if (node.outputs?.[0]) {
node.outputs[0].type = type;
node.outputs[0].name = type;
}
}
}
} else {
node.inputs[0].type = "*";
node.inputs[0].name = "value";
if (node.outputs?.[0]) {
node.outputs[0].type = "*";
node.outputs[0].name = "value";
}
}
if (!widget) {
widget = ComfyWidgets.STRING(this, "_display", [
"STRING", { multiline: true }
], appInstance).widget;
widget.inputEl.readOnly = true;
widget.inputEl.style.opacity = "0.7";
widget.inputEl.style.fontFamily = "monospace";
widget.inputEl.style.fontSize = "12px";
}
};
const text = Array.isArray(message.text) ? message.text[0] : message.text;
widget.value = text || "";
// Resize node
requestAnimationFrame(() => {
const sz = this.computeSize();
if (sz[0] < this.size[0]) sz[0] = this.size[0];
if (sz[1] < this.size[1]) sz[1] = this.size[1];
this.onResize?.(sz);
appInstance.graph?.setDirtyCanvas(true, false);
});
}
};
}
if (nodeData.name === "SimpleGet") {
// Update title based on name
const onNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = function() {
if (onNodeCreated) onNodeCreated.apply(this, arguments);
const node = this;
this.isVirtualNode = true;
// Replace name widget with combo that shows available setters
const nameWidget = this.widgets?.find(w => w.name === "name");
if (nameWidget) {
// Convert to combo widget
nameWidget.type = "combo";
nameWidget.options = {
values: () => {
if (!node.graph?._nodes) return [""];
const names = node.graph._nodes
.filter(n => n.type === "SimpleSet")
.map(n => n.widgets?.find(w => w.name === "name")?.value || "")
.filter(n => n !== "");
return ["", ...names.sort()];
}
};
const origCallback = nameWidget.callback;
nameWidget.callback = function(value) {
if (origCallback) origCallback.apply(this, arguments);
node.title = value ? `Get: ${value}` : "SimpleGet";
node.syncWithSetter();
if (nodeData.name === "SimpleSet") {
node.title = value ? `Set: ${value}` : "SimpleSet";
} else if (nodeData.name === "SimpleGet") {
node.title = value ? `Get: ${value}` : "SimpleGet";
}
};
}
this.syncWithSetter = function() {
const setter = this.findSetter();
if (setter?.inputs?.[0] && this.outputs?.[0]) {
this.outputs[0].type = setter.inputs[0].type || "*";
this.outputs[0].name = setter.inputs[0].name || "value";
} else if (this.outputs?.[0]) {
this.outputs[0].type = "*";
this.outputs[0].name = "value";
}
};
this.findSetter = function() {
if (!this.graph) return null;
const name = this.widgets?.find(w => w.name === "name")?.value;
if (!name) return null;
return this.graph._nodes.find(n =>
n.type === "SimpleSet" &&
n.widgets?.find(w => w.name === "name")?.value === name
);
};
// Override getInputLink to get data from setter
this.getInputLink = function(slot) {
const setter = this.findSetter();
if (setter?.inputs?.[0]?.link != null) {
return this.graph.links[setter.inputs[0].link];
}
return null;
};
};
}
}