Skip to content
This repository was archived by the owner on Sep 15, 2025. It is now read-only.

Commit 6f0dd4d

Browse files
authored
Add files via upload
1 parent c15843e commit 6f0dd4d

File tree

6 files changed

+1767
-818
lines changed

6 files changed

+1767
-818
lines changed

web/js/IFChatPromptNode.js

Lines changed: 531 additions & 531 deletions
Large diffs are not rendered by default.
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import { app } from "/scripts/app.js";
2+
import { ComfyWidgets } from "/scripts/widgets.js";
3+
4+
app.registerExtension({
5+
name: "Comfy.IFDisplayTextWildcardNode",
6+
async beforeRegisterNodeDef(nodeType, nodeData, app) {
7+
if (nodeData.name === "IF_DisplayTextWildcard") {
8+
// Store original node methods
9+
const onNodeCreated = nodeType.prototype.onNodeCreated;
10+
const onExecuted = nodeType.prototype.onExecuted;
11+
const onDrawForeground = nodeType.prototype.onDrawForeground;
12+
const getExtraMenuOptions = nodeType.prototype.getExtraMenuOptions;
13+
14+
// Add counter status display
15+
nodeType.prototype.counterStatus = {
16+
count: -1,
17+
blocked: false
18+
};
19+
20+
nodeType.prototype.onNodeCreated = function () {
21+
const ret = onNodeCreated?.apply(this, arguments);
22+
23+
// Set output labels
24+
if (this.outputs) {
25+
this.outputs[0].name = "text";
26+
this.outputs[1].name = "text_list";
27+
this.outputs[2].name = "count";
28+
this.outputs[3].name = "selected";
29+
30+
// Set the text_list output to use grid shape
31+
this.outputs[1].shape = LiteGraph.GRID_SHAPE;
32+
}
33+
34+
// Create unique name for node instance
35+
let nodeName = `${nodeData.name}_${app.graph._nodes.filter(n => n.type === nodeData.name).length}`;
36+
console.log(`Create ${nodeData.name}: ${nodeName}`);
37+
38+
// Create text display widget
39+
const wi = ComfyWidgets.STRING(
40+
this,
41+
nodeName,
42+
["STRING", {
43+
default: "",
44+
placeholder: "Message will appear here ...",
45+
multiline: true,
46+
}],
47+
app
48+
);
49+
wi.widget.inputEl.readOnly = true;
50+
51+
return ret;
52+
};
53+
54+
// Handle counter status updates
55+
nodeType.prototype.onExecuted = function (message) {
56+
const ret = onExecuted?.apply(this, arguments);
57+
58+
// Update counter status
59+
const widgets = this.widgets || [];
60+
const counterWidget = widgets.find(w => w.name === "counter");
61+
62+
if (counterWidget) {
63+
// Get counter value from widget
64+
this.counterStatus.count = counterWidget.value;
65+
66+
// Check if execution was blocked
67+
if (message?.error?.includes("Counter reached 0")) {
68+
this.counterStatus.blocked = true;
69+
} else {
70+
this.counterStatus.blocked = false;
71+
}
72+
}
73+
74+
// Update text display
75+
if (message?.string) {
76+
const widget_id = this.widgets.findIndex(w => w.type === "customtext");
77+
if (widget_id !== -1) {
78+
let texts = message.string;
79+
if (Array.isArray(texts)) {
80+
texts = texts
81+
.filter(text => text != null)
82+
.map(text => String(text).trim())
83+
.join("\n");
84+
} else {
85+
texts = String(texts).trim();
86+
}
87+
this.widgets[widget_id].value = texts;
88+
}
89+
}
90+
91+
app.graph.setDirtyCanvas(true);
92+
return ret;
93+
};
94+
95+
// Enhanced node drawing
96+
nodeType.prototype.onDrawForeground = function (ctx) {
97+
const ret = onDrawForeground?.apply(this, arguments);
98+
99+
// Add tooltips to outputs
100+
if (this.outputs) {
101+
const outputLabels = [
102+
"Complete Text",
103+
"List of Lines",
104+
"Line Count",
105+
"Selected Line"
106+
];
107+
const outputTooltips = [
108+
"Full text content",
109+
"Individual lines as separate outputs",
110+
"Total number of non-empty lines",
111+
"Currently selected line based on select input"
112+
];
113+
114+
for (let i = 0; i < this.outputs.length; i++) {
115+
const output = this.outputs[i];
116+
output.tooltip = outputTooltips[i];
117+
}
118+
}
119+
120+
// Draw counter status
121+
if (this.counterStatus.count !== -1) {
122+
ctx.save();
123+
ctx.font = "12px Arial";
124+
ctx.textAlign = "right";
125+
126+
// Position in top-right corner
127+
const text = `Counter: ${this.counterStatus.count}`;
128+
const x = this.size[0] - 5;
129+
const y = 20;
130+
131+
// Draw counter value with color based on status
132+
if (this.counterStatus.blocked) {
133+
ctx.fillStyle = "#ff4444";
134+
this.boxcolor = "#442222";
135+
} else if (this.counterStatus.count === 0) {
136+
ctx.fillStyle = "#ffaa44";
137+
this.boxcolor = "#443322";
138+
} else {
139+
ctx.fillStyle = "#66ff66";
140+
this.boxcolor = null; // Reset to default
141+
}
142+
143+
ctx.fillText(text, x, y);
144+
ctx.restore();
145+
}
146+
147+
return ret;
148+
};
149+
150+
// Add counter reset option to context menu
151+
nodeType.prototype.getExtraMenuOptions = function (_, options) {
152+
const ret = getExtraMenuOptions?.apply(this, arguments);
153+
154+
options.push(
155+
null, // separator
156+
{
157+
content: "Reset Counter",
158+
callback: () => {
159+
const counterWidget = this.widgets.find(w => w.name === "counter");
160+
if (counterWidget) {
161+
// Reset to widget's original value
162+
counterWidget.value = counterWidget.options.default;
163+
this.counterStatus.count = counterWidget.value;
164+
this.counterStatus.blocked = false;
165+
app.graph.setDirtyCanvas(true);
166+
}
167+
}
168+
}
169+
);
170+
171+
return ret;
172+
};
173+
}
174+
},
175+
});

0 commit comments

Comments
 (0)