commit f6ee537ab6bcee4cf4f2230727f170de806f1067 Author: jessesep Date: Fri Dec 5 00:32:25 2025 +0100 Initial commit: ComfyUI Simple Variables node pack Set/Get variable nodes for Image, Mask, Latent, Conditioning, Model, CLIP, VAE, String, Int, Float, and Any types. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f04ed4f --- /dev/null +++ b/README.md @@ -0,0 +1,95 @@ +# ComfyUI Simple Variables + +A custom node pack for ComfyUI that provides **Set/Get variable nodes** for storing and retrieving data by name across your workflow. + +## Features + +- Store any ComfyUI data type with a custom variable name +- Retrieve stored variables anywhere in your workflow +- Reduces wire clutter by allowing "wireless" data transfer +- Passthrough design - Set nodes output the same data they receive + +## Supported Variable Types + +| Type | Set Node | Get Node | Category | +|------|----------|----------|----------| +| Image | Set Image Variable | Get Image Variable | `variables/image` | +| Mask | Set Mask Variable | Get Mask Variable | `variables/mask` | +| Latent | Set Latent Variable | Get Latent Variable | `variables/latent` | +| Conditioning | Set Conditioning Variable | Get Conditioning Variable | `variables/conditioning` | +| Model | Set Model Variable | Get Model Variable | `variables/model` | +| CLIP | Set CLIP Variable | Get CLIP Variable | `variables/clip` | +| VAE | Set VAE Variable | Get VAE Variable | `variables/vae` | +| String | Set String Variable | Get String Variable | `variables/primitive` | +| Int | Set Int Variable | Get Int Variable | `variables/primitive` | +| Float | Set Float Variable | Get Float Variable | `variables/primitive` | +| Any | Set Any Variable | Get Any Variable | `variables` | + +### Utility Nodes + +- **List All Variables** - Shows all currently stored variables and their types + +## Installation + +1. Clone this repository into your ComfyUI `custom_nodes` folder: + ```bash + cd ComfyUI/custom_nodes + git clone SimpleImageVariables + ``` + +2. Restart ComfyUI + +3. Search for "variable" in the node menu + +## Usage + +### Basic Example + +``` +[Load Image] → [Set Image Variable] (name: "reference") + ↓ + (passes image through to next node) + +... elsewhere in workflow ... + +[Get Image Variable] (name: "reference") → [Use Image Node] +``` + +### How It Works + +1. **Set nodes** store the input data in memory with your chosen variable name +2. **Set nodes** also pass the data through, so you can continue your workflow normally +3. **Get nodes** retrieve the stored data by variable name +4. Variables persist for the duration of the ComfyUI session + +### Tips + +- Use descriptive variable names like `"upscaled_image"` or `"final_mask"` +- The **Set Any Variable** node accepts any data type (useful for custom node outputs) +- Use **List All Variables** to debug and see what's currently stored +- Variables are cleared when ComfyUI restarts + +## Node Details + +### Set Nodes +- **Inputs**: + - `data` - The data to store (type depends on node) + - `variable_name` - String name for the variable +- **Outputs**: Same data that was input (passthrough) + +### Get Nodes +- **Inputs**: + - `variable_name` - String name of the variable to retrieve +- **Outputs**: The stored data + +### Error Handling + +If you try to Get a variable that hasn't been Set, you'll receive an error message listing all available variable names. + +## License + +MIT License - Free to use and modify. + +## Credits + +Created with assistance from Claude (Anthropic) for ComfyUI workflow optimization. diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..8cf04a4 --- /dev/null +++ b/__init__.py @@ -0,0 +1,486 @@ +""" +Simple Variables - Set and Get nodes for storing/retrieving data by name +Supports: Image, Mask, Latent, Conditioning, Model, CLIP, VAE, String, Int, Float, Any +""" + +# Global storage for variables +_variable_storage = {} + + +# ============== IMAGE ============== +class SetImageVariable: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "image": ("IMAGE",), + "variable_name": ("STRING", {"default": "my_image"}), + } + } + RETURN_TYPES = ("IMAGE",) + RETURN_NAMES = ("image",) + FUNCTION = "set_var" + CATEGORY = "variables/image" + + def set_var(self, image, variable_name): + _variable_storage[variable_name] = image + return (image,) + + +class GetImageVariable: + @classmethod + def INPUT_TYPES(cls): + return {"required": {"variable_name": ("STRING", {"default": "my_image"})}} + RETURN_TYPES = ("IMAGE",) + RETURN_NAMES = ("image",) + FUNCTION = "get_var" + CATEGORY = "variables/image" + + def get_var(self, variable_name): + if variable_name in _variable_storage: + return (_variable_storage[variable_name],) + raise ValueError(f"Variable '{variable_name}' not found") + + +# ============== MASK ============== +class SetMaskVariable: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "mask": ("MASK",), + "variable_name": ("STRING", {"default": "my_mask"}), + } + } + RETURN_TYPES = ("MASK",) + RETURN_NAMES = ("mask",) + FUNCTION = "set_var" + CATEGORY = "variables/mask" + + def set_var(self, mask, variable_name): + _variable_storage[variable_name] = mask + return (mask,) + + +class GetMaskVariable: + @classmethod + def INPUT_TYPES(cls): + return {"required": {"variable_name": ("STRING", {"default": "my_mask"})}} + RETURN_TYPES = ("MASK",) + RETURN_NAMES = ("mask",) + FUNCTION = "get_var" + CATEGORY = "variables/mask" + + def get_var(self, variable_name): + if variable_name in _variable_storage: + return (_variable_storage[variable_name],) + raise ValueError(f"Variable '{variable_name}' not found") + + +# ============== LATENT ============== +class SetLatentVariable: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "latent": ("LATENT",), + "variable_name": ("STRING", {"default": "my_latent"}), + } + } + RETURN_TYPES = ("LATENT",) + RETURN_NAMES = ("latent",) + FUNCTION = "set_var" + CATEGORY = "variables/latent" + + def set_var(self, latent, variable_name): + _variable_storage[variable_name] = latent + return (latent,) + + +class GetLatentVariable: + @classmethod + def INPUT_TYPES(cls): + return {"required": {"variable_name": ("STRING", {"default": "my_latent"})}} + RETURN_TYPES = ("LATENT",) + RETURN_NAMES = ("latent",) + FUNCTION = "get_var" + CATEGORY = "variables/latent" + + def get_var(self, variable_name): + if variable_name in _variable_storage: + return (_variable_storage[variable_name],) + raise ValueError(f"Variable '{variable_name}' not found") + + +# ============== CONDITIONING ============== +class SetConditioningVariable: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "conditioning": ("CONDITIONING",), + "variable_name": ("STRING", {"default": "my_cond"}), + } + } + RETURN_TYPES = ("CONDITIONING",) + RETURN_NAMES = ("conditioning",) + FUNCTION = "set_var" + CATEGORY = "variables/conditioning" + + def set_var(self, conditioning, variable_name): + _variable_storage[variable_name] = conditioning + return (conditioning,) + + +class GetConditioningVariable: + @classmethod + def INPUT_TYPES(cls): + return {"required": {"variable_name": ("STRING", {"default": "my_cond"})}} + RETURN_TYPES = ("CONDITIONING",) + RETURN_NAMES = ("conditioning",) + FUNCTION = "get_var" + CATEGORY = "variables/conditioning" + + def get_var(self, variable_name): + if variable_name in _variable_storage: + return (_variable_storage[variable_name],) + raise ValueError(f"Variable '{variable_name}' not found") + + +# ============== MODEL ============== +class SetModelVariable: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "model": ("MODEL",), + "variable_name": ("STRING", {"default": "my_model"}), + } + } + RETURN_TYPES = ("MODEL",) + RETURN_NAMES = ("model",) + FUNCTION = "set_var" + CATEGORY = "variables/model" + + def set_var(self, model, variable_name): + _variable_storage[variable_name] = model + return (model,) + + +class GetModelVariable: + @classmethod + def INPUT_TYPES(cls): + return {"required": {"variable_name": ("STRING", {"default": "my_model"})}} + RETURN_TYPES = ("MODEL",) + RETURN_NAMES = ("model",) + FUNCTION = "get_var" + CATEGORY = "variables/model" + + def get_var(self, variable_name): + if variable_name in _variable_storage: + return (_variable_storage[variable_name],) + raise ValueError(f"Variable '{variable_name}' not found") + + +# ============== CLIP ============== +class SetClipVariable: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "clip": ("CLIP",), + "variable_name": ("STRING", {"default": "my_clip"}), + } + } + RETURN_TYPES = ("CLIP",) + RETURN_NAMES = ("clip",) + FUNCTION = "set_var" + CATEGORY = "variables/clip" + + def set_var(self, clip, variable_name): + _variable_storage[variable_name] = clip + return (clip,) + + +class GetClipVariable: + @classmethod + def INPUT_TYPES(cls): + return {"required": {"variable_name": ("STRING", {"default": "my_clip"})}} + RETURN_TYPES = ("CLIP",) + RETURN_NAMES = ("clip",) + FUNCTION = "get_var" + CATEGORY = "variables/clip" + + def get_var(self, variable_name): + if variable_name in _variable_storage: + return (_variable_storage[variable_name],) + raise ValueError(f"Variable '{variable_name}' not found") + + +# ============== VAE ============== +class SetVaeVariable: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "vae": ("VAE",), + "variable_name": ("STRING", {"default": "my_vae"}), + } + } + RETURN_TYPES = ("VAE",) + RETURN_NAMES = ("vae",) + FUNCTION = "set_var" + CATEGORY = "variables/vae" + + def set_var(self, vae, variable_name): + _variable_storage[variable_name] = vae + return (vae,) + + +class GetVaeVariable: + @classmethod + def INPUT_TYPES(cls): + return {"required": {"variable_name": ("STRING", {"default": "my_vae"})}} + RETURN_TYPES = ("VAE",) + RETURN_NAMES = ("vae",) + FUNCTION = "get_var" + CATEGORY = "variables/vae" + + def get_var(self, variable_name): + if variable_name in _variable_storage: + return (_variable_storage[variable_name],) + raise ValueError(f"Variable '{variable_name}' not found") + + +# ============== STRING ============== +class SetStringVariable: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "string": ("STRING", {"forceInput": True}), + "variable_name": ("STRING", {"default": "my_string"}), + } + } + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("string",) + FUNCTION = "set_var" + CATEGORY = "variables/primitive" + + def set_var(self, string, variable_name): + _variable_storage[variable_name] = string + return (string,) + + +class GetStringVariable: + @classmethod + def INPUT_TYPES(cls): + return {"required": {"variable_name": ("STRING", {"default": "my_string"})}} + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("string",) + FUNCTION = "get_var" + CATEGORY = "variables/primitive" + + def get_var(self, variable_name): + if variable_name in _variable_storage: + return (_variable_storage[variable_name],) + raise ValueError(f"Variable '{variable_name}' not found") + + +# ============== INT ============== +class SetIntVariable: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "value": ("INT", {"forceInput": True}), + "variable_name": ("STRING", {"default": "my_int"}), + } + } + RETURN_TYPES = ("INT",) + RETURN_NAMES = ("value",) + FUNCTION = "set_var" + CATEGORY = "variables/primitive" + + def set_var(self, value, variable_name): + _variable_storage[variable_name] = value + return (value,) + + +class GetIntVariable: + @classmethod + def INPUT_TYPES(cls): + return {"required": {"variable_name": ("STRING", {"default": "my_int"})}} + RETURN_TYPES = ("INT",) + RETURN_NAMES = ("value",) + FUNCTION = "get_var" + CATEGORY = "variables/primitive" + + def get_var(self, variable_name): + if variable_name in _variable_storage: + return (_variable_storage[variable_name],) + raise ValueError(f"Variable '{variable_name}' not found") + + +# ============== FLOAT ============== +class SetFloatVariable: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "value": ("FLOAT", {"forceInput": True}), + "variable_name": ("STRING", {"default": "my_float"}), + } + } + RETURN_TYPES = ("FLOAT",) + RETURN_NAMES = ("value",) + FUNCTION = "set_var" + CATEGORY = "variables/primitive" + + def set_var(self, value, variable_name): + _variable_storage[variable_name] = value + return (value,) + + +class GetFloatVariable: + @classmethod + def INPUT_TYPES(cls): + return {"required": {"variable_name": ("STRING", {"default": "my_float"})}} + RETURN_TYPES = ("FLOAT",) + RETURN_NAMES = ("value",) + FUNCTION = "get_var" + CATEGORY = "variables/primitive" + + def get_var(self, variable_name): + if variable_name in _variable_storage: + return (_variable_storage[variable_name],) + raise ValueError(f"Variable '{variable_name}' not found") + + +# ============== ANY (Universal) ============== +class SetAnyVariable: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "variable_name": ("STRING", {"default": "my_var"}), + }, + "optional": { + "any": ("*",), + } + } + RETURN_TYPES = ("*",) + RETURN_NAMES = ("any",) + FUNCTION = "set_var" + CATEGORY = "variables" + + def set_var(self, variable_name, any=None): + _variable_storage[variable_name] = any + return (any,) + + +class GetAnyVariable: + @classmethod + def INPUT_TYPES(cls): + return {"required": {"variable_name": ("STRING", {"default": "my_var"})}} + RETURN_TYPES = ("*",) + RETURN_NAMES = ("any",) + FUNCTION = "get_var" + CATEGORY = "variables" + + def get_var(self, variable_name): + if variable_name in _variable_storage: + return (_variable_storage[variable_name],) + raise ValueError(f"Variable '{variable_name}' not found. Available: {list(_variable_storage.keys())}") + + +# ============== LIST VARIABLES ============== +class ListVariables: + @classmethod + def INPUT_TYPES(cls): + return {"required": {}} + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("variable_list",) + FUNCTION = "list_vars" + CATEGORY = "variables" + + def list_vars(self): + var_list = "\n".join([f"{k}: {type(v).__name__}" for k, v in _variable_storage.items()]) + return (var_list if var_list else "(no variables set)",) + + +NODE_CLASS_MAPPINGS = { + # Image + "SetImageVariable": SetImageVariable, + "GetImageVariable": GetImageVariable, + # Mask + "SetMaskVariable": SetMaskVariable, + "GetMaskVariable": GetMaskVariable, + # Latent + "SetLatentVariable": SetLatentVariable, + "GetLatentVariable": GetLatentVariable, + # Conditioning + "SetConditioningVariable": SetConditioningVariable, + "GetConditioningVariable": GetConditioningVariable, + # Model + "SetModelVariable": SetModelVariable, + "GetModelVariable": GetModelVariable, + # CLIP + "SetClipVariable": SetClipVariable, + "GetClipVariable": GetClipVariable, + # VAE + "SetVaeVariable": SetVaeVariable, + "GetVaeVariable": GetVaeVariable, + # String + "SetStringVariable": SetStringVariable, + "GetStringVariable": GetStringVariable, + # Int + "SetIntVariable": SetIntVariable, + "GetIntVariable": GetIntVariable, + # Float + "SetFloatVariable": SetFloatVariable, + "GetFloatVariable": GetFloatVariable, + # Any + "SetAnyVariable": SetAnyVariable, + "GetAnyVariable": GetAnyVariable, + # Utility + "ListVariables": ListVariables, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + # Image + "SetImageVariable": "Set Image Variable", + "GetImageVariable": "Get Image Variable", + # Mask + "SetMaskVariable": "Set Mask Variable", + "GetMaskVariable": "Get Mask Variable", + # Latent + "SetLatentVariable": "Set Latent Variable", + "GetLatentVariable": "Get Latent Variable", + # Conditioning + "SetConditioningVariable": "Set Conditioning Variable", + "GetConditioningVariable": "Get Conditioning Variable", + # Model + "SetModelVariable": "Set Model Variable", + "GetModelVariable": "Get Model Variable", + # CLIP + "SetClipVariable": "Set CLIP Variable", + "GetClipVariable": "Get CLIP Variable", + # VAE + "SetVaeVariable": "Set VAE Variable", + "GetVaeVariable": "Get VAE Variable", + # String + "SetStringVariable": "Set String Variable", + "GetStringVariable": "Get String Variable", + # Int + "SetIntVariable": "Set Int Variable", + "GetIntVariable": "Get Int Variable", + # Float + "SetFloatVariable": "Set Float Variable", + "GetFloatVariable": "Get Float Variable", + # Any + "SetAnyVariable": "Set Any Variable", + "GetAnyVariable": "Get Any Variable", + # Utility + "ListVariables": "List All Variables", +}