Add files via upload
This commit is contained in:
@@ -155,7 +155,17 @@ A utility node that passes an image through unchanged but extracts its width and
|
||||
|
||||
---
|
||||
|
||||
### 7. ✖️ Multiplication (Dual & Latent)
|
||||
### 7. 📏 Image Latent Resolution Extractor
|
||||
**Get pixel dimensions from a Latent.**
|
||||
|
||||
Standard Stable Diffusion latents are compressed (1/8th scale). This node reads the latent dimensions and multiplies them by 8 to give you the effective pixel width and height.
|
||||
|
||||
> **Use Case:**
|
||||
> Useful when you have a latent and need to know its target pixel size for downstream resizing or conditionings, without decoding it first.
|
||||
|
||||
---
|
||||
|
||||
### 8. ✖️ Multiplication (Dual & Latent)
|
||||
**Mathematical scaling for custom upscaling.**
|
||||
|
||||
Takes two integer inputs (like Width and Height) and an optional Latent, and multiplies them by a float factor.
|
||||
@@ -176,7 +186,7 @@ Takes two integer inputs (like Width and Height) and an optional Latent, and mul
|
||||
|
||||
---
|
||||
|
||||
### 8. 🧹 VRAM/RAM Cleaner
|
||||
### 9. 🧹 VRAM/RAM Cleaner
|
||||
**Manage your resources mid-workflow.**
|
||||
|
||||
A "Pass-through" node that can connect to **any** input (Model, VAE, Image, etc.). It passes the data through unchanged but triggers a garbage collection and VRAM flush event when executed.
|
||||
@@ -188,7 +198,7 @@ A "Pass-through" node that can connect to **any** input (Model, VAE, Image, etc.
|
||||
|
||||
---
|
||||
|
||||
### 9. 🎮 Flow Control (Sidecar Bypass)
|
||||
### 10. 🎮 Flow Control (Sidecar Bypass)
|
||||
**Toggle nodes On/Off remotely.**
|
||||
|
||||
A control panel that connects to up to 4 other nodes. This acts as a "Sidecar" — it does not sit in the flow of data, but rather controls the logic of the connected nodes.
|
||||
@@ -201,7 +211,7 @@ A control panel that connects to up to 4 other nodes. This acts as a "Sidecar"
|
||||
|
||||
---
|
||||
|
||||
### 10. 🔀 Any Passthrough
|
||||
### 11. 🔀 Any Passthrough
|
||||
**Universal rerouting tools.**
|
||||
|
||||
Use these to clean up "spaghetti" wires or create fallback logic. These nodes accept **any** connection type (Model, Image, String, Latent, etc.).
|
||||
@@ -211,21 +221,34 @@ Use these to clean up "spaghetti" wires or create fallback logic. These nodes ac
|
||||
|
||||
---
|
||||
|
||||
### 11. ⏱️ Add Delay
|
||||
### 12. ⏱️ Add Delay
|
||||
**Pause execution for debugging.**
|
||||
|
||||
A simple node that connects to any data type, waits for a specified number of seconds, and then passes the data through unchanged. Useful for timing API calls or debugging complex flows.
|
||||
|
||||
---
|
||||
|
||||
### 12. 📺 Show Text
|
||||
### 13. 🐞 Debug Data (Any Input)
|
||||
**Inspect your data connections.**
|
||||
|
||||
Not sure what shape a tensor is? Want to check the exact resolution of a latent? Connect **ANY** output to this node. It analyzes the data and displays a summary directly on the node.
|
||||
|
||||
> **Features:**
|
||||
> * **Images:** Displays Resolution, Aspect Ratio, Batch Size, and Channels.
|
||||
> * **Latents:** Displays Latent Shape and equivalent Pixel Resolution (8x).
|
||||
> * **General:** Displays Type, Tensor Shape, Dtype, and Device.
|
||||
> * **On-Graph Display:** Shows the data in a read-only "Matrix green" text box directly on the node itself.
|
||||
|
||||
---
|
||||
|
||||
### 14. 📺 Show Text
|
||||
**Display text directly on the graph.**
|
||||
|
||||
Connect any string output (like the `Prompt Queue` or `Camera Angle Control`) to this node. It will display the text content inside a widget box on the node itself. Useful for verifying what is actually being sent to your CLIP encoder.
|
||||
|
||||
---
|
||||
|
||||
### 13. 🎨 CLIP Text Encode (Prompt Enrichment)
|
||||
### 15. 🎨 CLIP Text Encode (Prompt Enrichment)
|
||||
**Standard conditioning with built-in style power.**
|
||||
|
||||
Why copy-paste "masterpiece, best quality, 4k..." every time? This node acts exactly like the standard CLIP Text Encode but includes a dropdown with **20 curated style presets**.
|
||||
@@ -246,7 +269,7 @@ Why copy-paste "masterpiece, best quality, 4k..." every time? This node acts exa
|
||||
|
||||
---
|
||||
|
||||
### 14. 🖱️ Visual Marquee (Interactive)
|
||||
### 16. 🖱️ Visual Marquee (Interactive)
|
||||
**Pause, Select, and Refine.**
|
||||
|
||||
A Human-in-the-Loop tool that pauses your workflow and opens a popup editor over your generated image. You can draw a crop box to select a specific area, then resume the workflow to process just that area.
|
||||
@@ -269,7 +292,7 @@ A Human-in-the-Loop tool that pauses your workflow and opens a popup editor over
|
||||
|
||||
---
|
||||
|
||||
### 15. 🧩 Tile Compositor (Merge)
|
||||
### 17. 🧩 Tile Compositor (Merge)
|
||||
**Seamlessly paste refined details back.**
|
||||
|
||||
The partner node to **Visual Marquee**. After you have processed/upscaled/inpainted your cropped area, this node puts it back into the original full-size image at the exact correct coordinates.
|
||||
@@ -280,7 +303,7 @@ The partner node to **Visual Marquee**. After you have processed/upscaled/inpain
|
||||
|
||||
---
|
||||
|
||||
### 16. 💎 Detail Enhancer
|
||||
### 18. 💎 Detail Enhancer
|
||||
**Inject texture and crispness.**
|
||||
|
||||
A specialized node that manipulates the noise schedule (Sigmas) to force the model to generate more high-frequency detail. It works by "slowing down" the sampling process during the critical detail-formation phase and artificially inflating noise values.
|
||||
@@ -302,7 +325,7 @@ A specialized node that manipulates the noise schedule (Sigmas) to force the mod
|
||||
|
||||
---
|
||||
|
||||
### 17. ☁️ LoRA Online
|
||||
### 19. ☁️ LoRA Online
|
||||
**Use LoRAs directly from URLs.**
|
||||
|
||||
Skip the manual download process. Paste a link from Civitai, Tensor.art, or HuggingFace, and this node will download the LoRA, load it into your model, and optionally delete it after generation to save disk space.
|
||||
@@ -359,6 +382,11 @@ Skip the manual download process. Paste a link from Civitai, Tensor.art, or Hugg
|
||||
4. Feed the Result, the Original Image, and the `tile_data` into **Tile Compositor**.
|
||||
5. Result: The original image with a high-res, refined detail pasted back in seamlessly.
|
||||
|
||||
### The "Debugger"
|
||||
1. Not sure if your latent is the right size?
|
||||
2. Connect your Latent to the **Debug Data** node.
|
||||
3. It instantly shows: `Latent Size: 128x128` and `Pixel Res: 1024x1024` right on the graph.
|
||||
|
||||
<br>
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
+15
-4
@@ -30,6 +30,11 @@ try:
|
||||
except ImportError:
|
||||
EXTRACT_CLASSES, EXTRACT_DISPLAY = {}, {}
|
||||
|
||||
try:
|
||||
from .image_latent_resolution_extractor_node import NODE_CLASS_MAPPINGS as LAT_EXT_CLASSES, NODE_DISPLAY_NAME_MAPPINGS as LAT_EXT_DISPLAY
|
||||
except ImportError:
|
||||
LAT_EXT_CLASSES, LAT_EXT_DISPLAY = {}, {}
|
||||
|
||||
try:
|
||||
from .multiplication_node import NODE_CLASS_MAPPINGS as MULT_CLASSES, NODE_DISPLAY_NAME_MAPPINGS as MULT_DISPLAY
|
||||
except ImportError:
|
||||
@@ -50,6 +55,12 @@ try:
|
||||
except ImportError:
|
||||
ANYPT_CLASSES, ANYPT_DISPLAY = {}, {}
|
||||
|
||||
# New Debug Node
|
||||
try:
|
||||
from .output_any_debug_data_node import NODE_CLASS_MAPPINGS as DEBUG_CLASSES, NODE_DISPLAY_NAME_MAPPINGS as DEBUG_DISPLAY
|
||||
except ImportError:
|
||||
DEBUG_CLASSES, DEBUG_DISPLAY = {}, {}
|
||||
|
||||
try:
|
||||
from .delay_node import NODE_CLASS_MAPPINGS as DELAY_CLASSES, NODE_DISPLAY_NAME_MAPPINGS as DELAY_DISPLAY
|
||||
except ImportError:
|
||||
@@ -65,25 +76,21 @@ try:
|
||||
except ImportError:
|
||||
ENRICH_CLASSES, ENRICH_DISPLAY = {}, {}
|
||||
|
||||
# Tile Compositor (and Manager)
|
||||
try:
|
||||
from .tile_manager_nodes import NODE_CLASS_MAPPINGS as TILE_CLASSES, NODE_DISPLAY_NAME_MAPPINGS as TILE_DISPLAY
|
||||
except ImportError:
|
||||
TILE_CLASSES, TILE_DISPLAY = {}, {}
|
||||
|
||||
# Visual Marquee (Popup/JS based)
|
||||
try:
|
||||
from .visual_marquee_node import NODE_CLASS_MAPPINGS as VIS_CLASSES, NODE_DISPLAY_NAME_MAPPINGS as VIS_DISPLAY
|
||||
except ImportError:
|
||||
VIS_CLASSES, VIS_DISPLAY = {}, {}
|
||||
|
||||
# Detail Enhancer
|
||||
try:
|
||||
from .detail_enhance_node import NODE_CLASS_MAPPINGS as DETAIL_CLASSES, NODE_DISPLAY_NAME_MAPPINGS as DETAIL_DISPLAY
|
||||
except ImportError:
|
||||
DETAIL_CLASSES, DETAIL_DISPLAY = {}, {}
|
||||
|
||||
# LoRA Online Loader
|
||||
try:
|
||||
from .lora_online_node import NODE_CLASS_MAPPINGS as LORA_ONLINE_CLASSES, NODE_DISPLAY_NAME_MAPPINGS as LORA_ONLINE_DISPLAY
|
||||
except ImportError:
|
||||
@@ -97,10 +104,12 @@ NODE_CLASS_MAPPINGS = {
|
||||
**RES_CLASSES,
|
||||
**FIT_CLASSES,
|
||||
**EXTRACT_CLASSES,
|
||||
**LAT_EXT_CLASSES,
|
||||
**MULT_CLASSES,
|
||||
**CLEAN_CLASSES,
|
||||
**FLOW_CLASSES,
|
||||
**ANYPT_CLASSES,
|
||||
**DEBUG_CLASSES,
|
||||
**DELAY_CLASSES,
|
||||
**DT_CLASSES,
|
||||
**ENRICH_CLASSES,
|
||||
@@ -117,10 +126,12 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
**RES_DISPLAY,
|
||||
**FIT_DISPLAY,
|
||||
**EXTRACT_DISPLAY,
|
||||
**LAT_EXT_DISPLAY,
|
||||
**MULT_DISPLAY,
|
||||
**CLEAN_DISPLAY,
|
||||
**FLOW_DISPLAY,
|
||||
**ANYPT_DISPLAY,
|
||||
**DEBUG_DISPLAY,
|
||||
**DELAY_DISPLAY,
|
||||
**DT_DISPLAY,
|
||||
**ENRICH_DISPLAY,
|
||||
|
||||
@@ -225,4 +225,4 @@ NODE_CLASS_MAPPINGS = {
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"CameraAngleControl": "Camera Angle Control",
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import torch
|
||||
|
||||
class ImageLatentResolutionExtractorNode:
|
||||
"""
|
||||
A utility node that takes a LATENT (samples) as input and extracts its
|
||||
corresponding pixel resolution (Width and Height).
|
||||
|
||||
Standard Stable Diffusion latents are 1/8th the size of the pixel image.
|
||||
This node calculates: Pixel Size = Latent Size * 8.
|
||||
|
||||
- Input: samples (Latent)
|
||||
- Outputs: Latent (Passthrough), Width (Int), Height (Int)
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"samples": ("LATENT",),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LATENT", "INT", "INT")
|
||||
RETURN_NAMES = ("latent", "width", "height")
|
||||
FUNCTION = "extract_resolution"
|
||||
CATEGORY = "flow-assistor"
|
||||
|
||||
def extract_resolution(self, samples):
|
||||
# samples is a dictionary: {'samples': Tensor[Batch, Channels, Height, Width]}
|
||||
latent_tensor = samples["samples"]
|
||||
|
||||
# Get dimensions from the tensor
|
||||
# Shape is [Batch, Channels, H, W]
|
||||
l_height = latent_tensor.shape[2]
|
||||
l_width = latent_tensor.shape[3]
|
||||
|
||||
# Convert to pixel dimensions (Standard SD factor is 8)
|
||||
# We assume square pixels
|
||||
pixel_width = int(l_width * 8)
|
||||
pixel_height = int(l_height * 8)
|
||||
|
||||
return (
|
||||
samples, # Pass the latent through unchanged
|
||||
pixel_width,
|
||||
pixel_height
|
||||
)
|
||||
|
||||
# Node Registration
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"ImageLatentResolutionExtractorNode": ImageLatentResolutionExtractorNode,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"ImageLatentResolutionExtractorNode": "Image Latent Resolution Extractor",
|
||||
}
|
||||
@@ -5,11 +5,13 @@
|
||||
"ResolutionSelectNode": "Resolution Selector (Groups)",
|
||||
"ImageResolutionFitNode": "Image Resolution Fit",
|
||||
"ImageResolutionExtractorNode": "Image Resolution Extractor",
|
||||
"ImageLatentResolutionExtractorNode": "Image Latent Resolution Extractor",
|
||||
"MultiplicationNode": "Multiplication (Dual & Latent)",
|
||||
"VRAMRAMCleanerNode": "VRAM/RAM Cleaner",
|
||||
"BypassControl": "Flow Control (Sidecar Bypass)",
|
||||
"AnyPassthrough6to1": "Any Passthrough (6 → 1)",
|
||||
"AnyPassthrough1to6": "Any Passthrough (1 → 6)",
|
||||
"OutputAnyDebugDataNode": "Debug Data (Any Input)",
|
||||
"AddDelay": "Add Delay",
|
||||
"DisplayText": "Show Text",
|
||||
"CLIPTextEncodePromptEnrichment": "CLIP Text Encode (Prompt Enrichment)",
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
import torch
|
||||
|
||||
# Special AnyType to allow any connection
|
||||
class AnyType(str):
|
||||
def __ne__(self, __value: object) -> bool:
|
||||
return False
|
||||
|
||||
any_type = AnyType("*")
|
||||
|
||||
class OutputAnyDebugDataNode:
|
||||
"""
|
||||
A debug node that accepts ANY input and analyzes it.
|
||||
- If IMAGE: Shows resolution (WxH), Aspect Ratio, and Batch Size.
|
||||
- If LATENT: Shows Latent Dimensions and equivalent Pixel Resolution (8x).
|
||||
- If other: Shows Type and raw string representation.
|
||||
|
||||
The result is displayed as text on the node itself (via JS) and output as a string.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"any_input": (any_type,),
|
||||
},
|
||||
"hidden": {
|
||||
"unique_id": "UNIQUE_ID",
|
||||
"extra_pnginfo": "EXTRA_PNGINFO",
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("debug_text",)
|
||||
FUNCTION = "analyze_data"
|
||||
CATEGORY = "flow-assistor/debug"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def analyze_data(self, any_input, unique_id=None, extra_pnginfo=None):
|
||||
text_output = "None"
|
||||
|
||||
try:
|
||||
# 1. Handle Torch Tensors (Images, Masks, Raw Latents)
|
||||
if isinstance(any_input, torch.Tensor):
|
||||
shape = any_input.shape
|
||||
# Basic info
|
||||
text_output = f"Type: Tensor\nShape: {list(shape)}\nDtype: {any_input.dtype}\nDevice: {any_input.device}\n"
|
||||
|
||||
# Heuristic for IMAGE: [Batch, Height, Width, Channels]
|
||||
if any_input.ndim == 4:
|
||||
# Standard Image: Channels at end (usually 3 or 4)
|
||||
if shape[3] <= 4 and shape[1] > 8 and shape[2] > 8:
|
||||
b, h, w, c = shape
|
||||
ar = w / h if h > 0 else 0
|
||||
text_output += f"\n--- IMAGE DETECTED ---\n"
|
||||
text_output += f"Resolution: {w}x{h}\n"
|
||||
text_output += f"Aspect Ratio: {ar:.2f}\n"
|
||||
text_output += f"Batch Size: {b}\n"
|
||||
text_output += f"Channels: {c}"
|
||||
|
||||
# Raw Latent / NCHW: Channels at dim 1
|
||||
elif shape[1] <= 4 and shape[2] > 8 and shape[3] > 8:
|
||||
b, c, h, w = shape
|
||||
text_output += f"\n--- RAW LATENT/NCHW ---\n"
|
||||
text_output += f"Latent Size: {w}x{h}\n"
|
||||
text_output += f"Pixel Res (~8x): {w*8}x{h*8}\n"
|
||||
text_output += f"Batch Size: {b}"
|
||||
|
||||
# Heuristic for MASK: [Batch, Height, Width]
|
||||
elif any_input.ndim == 3:
|
||||
b, h, w = shape
|
||||
text_output += f"\n--- MASK DETECTED ---\n"
|
||||
text_output += f"Resolution: {w}x{h}\n"
|
||||
text_output += f"Batch Size: {b}"
|
||||
|
||||
# 2. Handle Latent Dictionary (Standard ComfyUI Latent Wrapper)
|
||||
elif isinstance(any_input, dict) and "samples" in any_input:
|
||||
samples = any_input["samples"]
|
||||
if isinstance(samples, torch.Tensor):
|
||||
# Shape: [Batch, 4, Height, Width]
|
||||
shape = samples.shape
|
||||
b, c, h, w = shape
|
||||
ar = w / h if h > 0 else 0
|
||||
|
||||
text_output = f"Type: LATENT (Dict)\nShape: {list(shape)}\n"
|
||||
text_output += f"\n--- RESOLUTION INFO ---\n"
|
||||
text_output += f"Latent Size: {w}x{h}\n"
|
||||
text_output += f"Pixel Res (8x): {w*8}x{h*8}\n"
|
||||
text_output += f"Aspect Ratio: {ar:.2f}\n"
|
||||
text_output += f"Batch Size: {b}"
|
||||
else:
|
||||
text_output = f"Type: LATENT (Dict)\nError: 'samples' is not a tensor."
|
||||
|
||||
# 3. Handle Lists
|
||||
elif isinstance(any_input, list):
|
||||
text_output = f"Type: List\nLength: {len(any_input)}\n"
|
||||
if len(any_input) > 0:
|
||||
text_output += f"Sample[0]: {str(any_input[0])[:50]}..."
|
||||
|
||||
# 4. Handle Basic Types
|
||||
elif isinstance(any_input, (int, float, bool, str)):
|
||||
text_output = f"Type: {type(any_input).__name__}\nValue: {any_input}"
|
||||
|
||||
# 5. Generic Fallback
|
||||
else:
|
||||
raw_str = str(any_input)
|
||||
text_output = f"Type: {type(any_input)}\n"
|
||||
text_output += f"Value: {raw_str[:200]}..." if len(raw_str) > 0 else "Empty"
|
||||
|
||||
except Exception as e:
|
||||
text_output = f"Error analyzing data: {str(e)}"
|
||||
|
||||
# Return: {"ui": {KEY: [LIST]}, "result": (TUPLE)}
|
||||
return {"ui": {"text": [text_output]}, "result": (text_output,)}
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"OutputAnyDebugDataNode": OutputAnyDebugDataNode,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"OutputAnyDebugDataNode": "Debug Data (Any Input)",
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "comfyui-flow-assistor"
|
||||
description = "Essential utility nodes for ComfyUI (Prompt Queue, Camera Control, Resolution Fit, etc.)"
|
||||
version = "1.0.5"
|
||||
version = "1.0.6"
|
||||
license = { file = "LICENSE.txt" }
|
||||
dependencies = []
|
||||
tags = ["utils", "prompt", "camera", "resolution", "workflow"]
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import { app } from "/scripts/app.js";
|
||||
import { ComfyWidgets } from "/scripts/widgets.js";
|
||||
|
||||
// Renders the debug text returned by OutputAnyDebugDataNode directly on the node.
|
||||
|
||||
app.registerExtension({
|
||||
name: "FlowAssistor.DebugData",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData) {
|
||||
if (nodeData.name !== "OutputAnyDebugDataNode") return;
|
||||
|
||||
// Helper to Create or Update the Text Widget
|
||||
function populate(text) {
|
||||
// 1. Try to find the existing widget to avoid flicker
|
||||
const widgetName = "debug_text_msg";
|
||||
let w = this.widgets?.find((w) => w.name === widgetName);
|
||||
|
||||
// 2. If it doesn't exist, create it
|
||||
if (!w) {
|
||||
// ComfyWidgets["STRING"] adds the widget to this.widgets automatically
|
||||
const widgetResult = ComfyWidgets["STRING"](
|
||||
this,
|
||||
widgetName,
|
||||
["STRING", { multiline: true }],
|
||||
app
|
||||
);
|
||||
w = widgetResult.widget;
|
||||
|
||||
// Styling to look like a debug console
|
||||
w.inputEl.readOnly = true;
|
||||
w.inputEl.style.opacity = 0.9;
|
||||
w.inputEl.style.backgroundColor = "#222";
|
||||
w.inputEl.style.color = "#0f0"; // Matrix green text
|
||||
w.inputEl.style.fontFamily = "monospace";
|
||||
w.inputEl.style.fontSize = "11px";
|
||||
w.inputEl.style.padding = "4px";
|
||||
}
|
||||
|
||||
// 3. Update the value
|
||||
w.value = text ?? "Waiting for data...";
|
||||
|
||||
// 4. Force Resize to fit content
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
// Hook: When the node executes (during prompt run)
|
||||
const onExecuted = nodeType.prototype.onExecuted;
|
||||
nodeType.prototype.onExecuted = function (message) {
|
||||
onExecuted?.apply(this, arguments);
|
||||
// "message.text" comes from the python return {"ui": {"text": ...}}
|
||||
// ComfyUI usually sends lists for UI elements
|
||||
const text = message?.text?.[0] ?? message?.text ?? "No Data";
|
||||
populate.call(this, text);
|
||||
};
|
||||
|
||||
// Hook: When the node loads from a workflow (restore saved state)
|
||||
const onConfigure = nodeType.prototype.onConfigure;
|
||||
nodeType.prototype.onConfigure = function () {
|
||||
onConfigure?.apply(this, arguments);
|
||||
// Restore the last seen value if it exists in the save file
|
||||
if (this.widgets_values && this.widgets_values.length) {
|
||||
// The read-only widget usually ends up being the last one in saved values
|
||||
// or we just check index 0 if it's the only widget
|
||||
const savedText = this.widgets_values[0];
|
||||
if (typeof savedText === "string") {
|
||||
populate.call(this, savedText);
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user