From e281f96475f9b55e6b70261335e118e39a216ab7 Mon Sep 17 00:00:00 2001 From: jessesep Date: Fri, 5 Dec 2025 01:39:13 +0100 Subject: [PATCH] Show preview directly on node instead of separate output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Changed return format to use {"ui": {"text": [preview]}, "result": (value,)} - Preview text now displays on the node itself like Show Text nodes - Removed separate preview output port - cleaner node design - Updated README to reflect on-node preview feature 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- README.md | 28 ++++++++------ __init__.py | 104 ++++++++++++++++++++++++---------------------------- 2 files changed, 63 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index 1fc8327..290dedd 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,9 @@ Restart ComfyUI and search for **"variable"**. | Node | Description | |------|-------------| -| **Set Variable** | Store any data with a name, outputs preview | -| **Get Variable** | Retrieve data by name, outputs preview | -| **List Variables** | Show all stored variables | +| **Set Variable** | Store any data with a name, shows preview on node | +| **Get Variable** | Retrieve data by name, shows preview on node | +| **List Variables** | Show all stored variables on node | | **Clear Variables** | Clear all stored variables | ## Usage @@ -26,29 +26,33 @@ Restart ComfyUI and search for **"variable"**. [Load Image] → [Set Variable] (name: "ref") ↓ value (passthrough) - preview → [Show Text] → "[ref] = Tensor [1, 512, 512, 3]" + + Node displays: "ref = Tensor [1, 512, 512, 3]" ... elsewhere ... [Get Variable] (name: "ref") → value → [Any Node] - → preview → "[ref] = Tensor [1, 512, 512, 3]" + + Node displays: "ref = Tensor [1, 512, 512, 3]" ``` ## Features - **Universal** - Works with all data types (Image, Mask, Latent, Model, etc.) -- **Preview output** - See what's stored (type + shape/value) +- **On-node preview** - See what's stored directly on the node (type + shape/value) - **Passthrough** - Set Variable passes data through - **Debug** - List Variables shows all stored data ## Preview Examples -| Data Type | Preview Output | -|-----------|----------------| -| Image | `[my_image] = Tensor [1, 512, 512, 3]` | -| String | `[prompt] = "a beautiful sunset..."` | -| Int | `[steps] = 20` | -| Model | `[my_model] = BaseModel` | +Preview is shown directly on each node: + +| Data Type | On-Node Display | +|-----------|-----------------| +| Image | `my_image = Tensor [1, 512, 512, 3]` | +| String | `prompt = "a beautiful sunset..."` | +| Int | `steps = 20` | +| Model | `my_model = BaseModel` | ## License diff --git a/__init__.py b/__init__.py index df55d1a..e9c3ba5 100644 --- a/__init__.py +++ b/__init__.py @@ -6,8 +6,30 @@ SimpleVariables - Set and Get nodes for storing/retrieving any data by name in C _variable_storage = {} +def get_preview_text(variable_name, value): + """Generate preview text for a value""" + if value is None: + return f"{variable_name} = None" + + type_name = type(value).__name__ + + if hasattr(value, 'shape'): + return f"{variable_name} = {type_name} {list(value.shape)}" + elif isinstance(value, str): + val_str = value[:50] + "..." if len(value) > 50 else value + return f'{variable_name} = "{val_str}"' + elif isinstance(value, (int, float, bool)): + return f"{variable_name} = {value}" + elif isinstance(value, list): + return f"{variable_name} = list[{len(value)}]" + elif isinstance(value, dict): + return f"{variable_name} = dict[{len(value)} keys]" + else: + return f"{variable_name} = {type_name}" + + class SetVariable: - """Store any data with a custom variable name""" + """Store any data with a custom variable name - shows preview on node""" @classmethod def INPUT_TYPES(cls): return { @@ -16,38 +38,22 @@ class SetVariable: }, "optional": { "value": ("*",), - }, - "hidden": { - "unique_id": "UNIQUE_ID", } } - RETURN_TYPES = ("*", "STRING",) - RETURN_NAMES = ("value", "preview",) + RETURN_TYPES = ("*",) + RETURN_NAMES = ("value",) FUNCTION = "set_var" CATEGORY = "variables" OUTPUT_NODE = True - def set_var(self, variable_name, unique_id=None, value=None): + def set_var(self, variable_name, value=None): _variable_storage[variable_name] = value - - # Create preview string - if value is None: - preview = f"[{variable_name}] = None" - else: - type_name = type(value).__name__ - if hasattr(value, 'shape'): - preview = f"[{variable_name}] = {type_name} {list(value.shape)}" - elif isinstance(value, (str, int, float, bool)): - val_str = str(value)[:50] + "..." if len(str(value)) > 50 else str(value) - preview = f"[{variable_name}] = {val_str}" - else: - preview = f"[{variable_name}] = {type_name}" - - return (value, preview,) + preview = get_preview_text(variable_name, value) + return {"ui": {"text": [preview]}, "result": (value,)} class GetVariable: - """Retrieve data by variable name""" + """Retrieve data by variable name - shows preview on node""" @classmethod def INPUT_TYPES(cls): return { @@ -55,10 +61,11 @@ class GetVariable: "variable_name": ("STRING", {"default": "my_var"}), } } - RETURN_TYPES = ("*", "STRING",) - RETURN_NAMES = ("value", "preview",) + RETURN_TYPES = ("*",) + RETURN_NAMES = ("value",) FUNCTION = "get_var" CATEGORY = "variables" + OUTPUT_NODE = True def get_var(self, variable_name): if variable_name not in _variable_storage: @@ -66,25 +73,12 @@ class GetVariable: raise ValueError(f"Variable '{variable_name}' not found. Available: {available}") value = _variable_storage[variable_name] - - # Create preview string - if value is None: - preview = f"[{variable_name}] = None" - else: - type_name = type(value).__name__ - if hasattr(value, 'shape'): - preview = f"[{variable_name}] = {type_name} {list(value.shape)}" - elif isinstance(value, (str, int, float, bool)): - val_str = str(value)[:50] + "..." if len(str(value)) > 50 else str(value) - preview = f"[{variable_name}] = {val_str}" - else: - preview = f"[{variable_name}] = {type_name}" - - return (value, preview,) + preview = get_preview_text(variable_name, value) + return {"ui": {"text": [preview]}, "result": (value,)} class ListVariables: - """Show all stored variables""" + """Show all stored variables on the node""" @classmethod def INPUT_TYPES(cls): return {"required": {}} @@ -92,24 +86,16 @@ class ListVariables: RETURN_NAMES = ("variable_list",) FUNCTION = "list_vars" CATEGORY = "variables" + OUTPUT_NODE = True def list_vars(self): if not _variable_storage: - return ("(no variables set)",) + text = "(no variables set)" + else: + lines = [get_preview_text(name, value) for name, value in _variable_storage.items()] + text = "\n".join(lines) - lines = [] - for name, value in _variable_storage.items(): - if value is None: - lines.append(f"{name}: None") - elif hasattr(value, 'shape'): - lines.append(f"{name}: {type(value).__name__} {list(value.shape)}") - elif isinstance(value, (str, int, float, bool)): - val_str = str(value)[:30] + "..." if len(str(value)) > 30 else str(value) - lines.append(f"{name}: {val_str}") - else: - lines.append(f"{name}: {type(value).__name__}") - - return ("\n".join(lines),) + return {"ui": {"text": [text]}, "result": (text,)} class ClearVariables: @@ -125,13 +111,17 @@ class ClearVariables: RETURN_NAMES = ("status",) FUNCTION = "clear_vars" CATEGORY = "variables" + OUTPUT_NODE = True def clear_vars(self, clear): if clear: count = len(_variable_storage) _variable_storage.clear() - return (f"Cleared {count} variable(s)",) - return ("Not cleared (set clear=True)",) + status = f"Cleared {count} variable(s)" + else: + status = "Not cleared (set clear=True)" + + return {"ui": {"text": [status]}, "result": (status,)} NODE_CLASS_MAPPINGS = {