From 2c76d5465b5bc465f92ff1b80efdcdf19fc61ea2 Mon Sep 17 00:00:00 2001 From: MachinePainting Date: Thu, 12 Feb 2026 01:13:35 -0800 Subject: [PATCH] Add Text String node, fix Show Text display with JS --- README.md | 13 ++++++---- js/show_text.js | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 js/show_text.js diff --git a/README.md b/README.md index 43f4963..264fed2 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ pip install -r requirements.txt --- -## Nodes (23 Total) +## Nodes (24 Total) ### Color Adjustment @@ -87,6 +87,7 @@ pip install -r requirements.txt | **Boolean Master Switch** | Control multiple booleans from one switch for controlling multiple switches with one master switch node | | **Seed Lock** | Lock/unlock seed values with a toggle to lock the current seed vaule, opposed to the standard where the following run seed value is locked | | **Text Notes** | Add comments and documentation to your workflow for organization | +| **Text String** | Simple text input node for passing strings to other nodes | | **Show Text** | Display and pass through text output from other nodes for debugging | (example) @@ -152,6 +153,10 @@ pip install -r requirements.txt - Optional title field - No inputs/outputs - purely organizational +### Text String +- Simple text input with multiline support +- Outputs STRING for connecting to other nodes + ### Show Text - Display text output from other nodes - Pass-through output for chaining @@ -162,10 +167,8 @@ pip install -r requirements.txt ## Changelog ### v2.0.2 -- **New Nodes:** Text Notes, Show Text utility nodes -- **Color Match Blend:** Added blend modes (normal, overlay, multiply, screen, soft light, hard light, color, luminosity, darken, lighten) -- **Color Adjust Blend:** Reworked flow - color match → blend mode → RGB adjustments -- **Selective Color Pro:** Fixed smooth color detection for natural-looking adjustments +- **New Nodes:** Text Notes, Text String, Show Text utility nodes +- **Organized Categories:** Nodes now grouped into subcategories (Color, Mask, Blend, Analysis, Util) ### v2.0.1 Updated Node Settings, Resolved Display Issues, Fixed Several Node structures. diff --git a/js/show_text.js b/js/show_text.js new file mode 100644 index 0000000..75acc5b --- /dev/null +++ b/js/show_text.js @@ -0,0 +1,68 @@ +import { app } from "../../../scripts/app.js"; +import { ComfyWidgets } from "../../../scripts/widgets.js"; + +// Displays input text on a node +app.registerExtension({ + name: "MachinePaintingNodes.ShowText", + async beforeRegisterNodeDef(nodeType, nodeData, app) { + if (nodeData.name === "ShowText") { + function populate(text) { + if (this.widgets) { + const isConvertedWidget = +!!this.inputs?.[0].widget; + for (let i = isConvertedWidget; i < this.widgets.length; i++) { + this.widgets[i].onRemove?.(); + } + this.widgets.length = isConvertedWidget; + } + const v = [...text]; + if (!v[0]) { + v.shift(); + } + for (let list of v) { + if (!(list instanceof Array)) list = [list]; + for (const l of list) { + const w = ComfyWidgets["STRING"](this, "text_" + this.widgets?.length ?? 0, ["STRING", { multiline: true }], app).widget; + w.inputEl.readOnly = true; + w.inputEl.style.opacity = 0.6; + w.value = l; + } + } + 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); + app.graph.setDirtyCanvas(true, false); + }); + } + + const onExecuted = nodeType.prototype.onExecuted; + nodeType.prototype.onExecuted = function (message) { + onExecuted?.apply(this, arguments); + populate.call(this, message.text); + }; + + const VALUES = Symbol(); + const configure = nodeType.prototype.configure; + nodeType.prototype.configure = function () { + this[VALUES] = arguments[0]?.widgets_values; + return configure?.apply(this, arguments); + }; + + const onConfigure = nodeType.prototype.onConfigure; + nodeType.prototype.onConfigure = function () { + onConfigure?.apply(this, arguments); + const widgets_values = this[VALUES]; + if (widgets_values?.length) { + requestAnimationFrame(() => { + populate.call(this, widgets_values.slice(+(widgets_values.length > 1 && this.inputs?.[0].widget))); + }); + } + }; + } + }, +});