Show preview directly on node instead of separate output
- 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 <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
+47
-57
@@ -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 = {
|
||||
|
||||
Reference in New Issue
Block a user