330 lines
11 KiB
Python
330 lines
11 KiB
Python
# "Design-focused node suite for ComfyUI."
|
|
# Copyright 2026 Augment Studio
|
|
# Augmentstudio.app
|
|
|
|
import os
|
|
import json
|
|
|
|
|
|
VARS_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "input")
|
|
VARS_FILE = os.path.join(VARS_DIR, "vars.txt")
|
|
|
|
|
|
def load_vars():
|
|
if os.path.exists(VARS_FILE):
|
|
try:
|
|
with open(VARS_FILE, "r") as f:
|
|
return json.load(f)
|
|
except:
|
|
return {}
|
|
return {}
|
|
|
|
|
|
def save_vars(data):
|
|
os.makedirs(VARS_DIR, exist_ok=True)
|
|
with open(VARS_FILE, "w") as f:
|
|
json.dump(data, f, indent=2)
|
|
|
|
|
|
def vars_summary():
|
|
data = load_vars()
|
|
if not data:
|
|
return "(no variables saved)"
|
|
return "\n".join(f"{k}: {v}" for k, v in data.items())
|
|
|
|
|
|
# ── SET ──────────────────────────────────────────────
|
|
class NumberVarSetNode:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"variable_name": ("STRING", {"default": "my_variable"}),
|
|
"value": ("FLOAT", {"default": 0.0, "step": 0.01}),
|
|
},
|
|
"optional": {
|
|
"trigger": ("TRIGGER",),
|
|
"input": ("FLOAT", {"forceInput": True}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("FLOAT", "AUGMENT_JSON", "TRIGGER")
|
|
RETURN_NAMES = ("number", "json_result", "trigger")
|
|
FUNCTION = "execute"
|
|
CATEGORY = "Augment/Utils"
|
|
OUTPUT_NODE = True
|
|
|
|
@classmethod
|
|
def VALIDATE_INPUTS(cls, **kwargs):
|
|
return True
|
|
|
|
def execute(self, variable_name, value, trigger=None, input=None):
|
|
v = input if input is not None else value
|
|
data = load_vars()
|
|
data[variable_name] = v
|
|
save_vars(data)
|
|
json_result = json.dumps({"node": "NumberVarSetNode", "variable": variable_name, "value": v, "type": "number"})
|
|
return {"ui": {"text": [vars_summary()]}, "result": (v, json_result, "done")}
|
|
|
|
|
|
# ── GET ──────────────────────────────────────────────
|
|
class NumberVarGetNode:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"variable_name": ("STRING", {"default": "my_variable"}),
|
|
},
|
|
"optional": {
|
|
"trigger": ("TRIGGER",),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("FLOAT", "AUGMENT_JSON", "TRIGGER")
|
|
RETURN_NAMES = ("number", "json_result", "trigger")
|
|
FUNCTION = "execute"
|
|
CATEGORY = "Augment/Utils"
|
|
OUTPUT_NODE = True
|
|
|
|
@classmethod
|
|
def VALIDATE_INPUTS(cls, **kwargs):
|
|
return True
|
|
|
|
def execute(self, variable_name, trigger=None):
|
|
data = load_vars()
|
|
value = data.get(variable_name, 0.0)
|
|
json_result = json.dumps({"node": "NumberVarGetNode", "variable": variable_name, "value": value, "type": "number"})
|
|
return {"ui": {"text": [vars_summary()]}, "result": (value, json_result, "done")}
|
|
|
|
|
|
# ── INCREMENT ────────────────────────────────────────
|
|
class NumberVarIncrementNode:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"variable_name": ("STRING", {"default": "my_variable"}),
|
|
"amount": ("FLOAT", {"default": 1.0, "step": 0.01}),
|
|
},
|
|
"optional": {
|
|
"trigger": ("TRIGGER",),
|
|
"input": ("FLOAT", {"forceInput": True}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("FLOAT", "AUGMENT_JSON", "TRIGGER")
|
|
RETURN_NAMES = ("number", "json_result", "trigger")
|
|
FUNCTION = "execute"
|
|
CATEGORY = "Augment/Utils"
|
|
OUTPUT_NODE = True
|
|
|
|
@classmethod
|
|
def VALIDATE_INPUTS(cls, **kwargs):
|
|
return True
|
|
|
|
def execute(self, variable_name, amount, trigger=None, input=None):
|
|
data = load_vars()
|
|
current = input if input is not None else data.get(variable_name, 0.0)
|
|
new_value = current + amount
|
|
data[variable_name] = new_value
|
|
save_vars(data)
|
|
json_result = json.dumps({"node": "NumberVarIncrementNode", "variable": variable_name, "value": new_value, "amount": amount, "type": "number"})
|
|
return {"ui": {"text": [vars_summary()]}, "result": (new_value, json_result, "done")}
|
|
|
|
|
|
# ── DECREMENT ────────────────────────────────────────
|
|
class NumberVarDecrementNode:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"variable_name": ("STRING", {"default": "my_variable"}),
|
|
"amount": ("FLOAT", {"default": 1.0, "step": 0.01}),
|
|
},
|
|
"optional": {
|
|
"trigger": ("TRIGGER",),
|
|
"input": ("FLOAT", {"forceInput": True}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("FLOAT", "AUGMENT_JSON", "TRIGGER")
|
|
RETURN_NAMES = ("number", "json_result", "trigger")
|
|
FUNCTION = "execute"
|
|
CATEGORY = "Augment/Utils"
|
|
OUTPUT_NODE = True
|
|
|
|
@classmethod
|
|
def VALIDATE_INPUTS(cls, **kwargs):
|
|
return True
|
|
|
|
def execute(self, variable_name, amount, trigger=None, input=None):
|
|
data = load_vars()
|
|
current = input if input is not None else data.get(variable_name, 0.0)
|
|
new_value = current - amount
|
|
data[variable_name] = new_value
|
|
save_vars(data)
|
|
json_result = json.dumps({"node": "NumberVarDecrementNode", "variable": variable_name, "value": new_value, "amount": amount, "type": "number"})
|
|
return {"ui": {"text": [vars_summary()]}, "result": (new_value, json_result, "done")}
|
|
|
|
|
|
# ── RESET ────────────────────────────────────────────
|
|
class NumberVarResetNode:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"variable_name": ("STRING", {"default": "my_variable"}),
|
|
},
|
|
"optional": {
|
|
"trigger": ("TRIGGER",),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("FLOAT", "AUGMENT_JSON", "TRIGGER")
|
|
RETURN_NAMES = ("number", "json_result", "trigger")
|
|
FUNCTION = "execute"
|
|
CATEGORY = "Augment/Utils"
|
|
OUTPUT_NODE = True
|
|
|
|
@classmethod
|
|
def VALIDATE_INPUTS(cls, **kwargs):
|
|
return True
|
|
|
|
def execute(self, variable_name, trigger=None):
|
|
data = load_vars()
|
|
data[variable_name] = 0.0
|
|
save_vars(data)
|
|
json_result = json.dumps({"node": "NumberVarResetNode", "variable": variable_name, "value": 0.0, "type": "number"})
|
|
return {"ui": {"text": [vars_summary()]}, "result": (0.0, json_result, "done")}
|
|
|
|
|
|
# ── STRING SET ────────────────────────────────────────
|
|
class StringVarSetNode:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"variable_name": ("STRING", {"default": "api_key"}),
|
|
"value": ("STRING", {"default": ""}),
|
|
},
|
|
"optional": {
|
|
"trigger": ("TRIGGER",),
|
|
"input": ("STRING", {"forceInput": True}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING", "AUGMENT_JSON", "TRIGGER")
|
|
RETURN_NAMES = ("text", "json_result", "trigger")
|
|
FUNCTION = "execute"
|
|
CATEGORY = "Augment/Utils"
|
|
OUTPUT_NODE = True
|
|
|
|
@classmethod
|
|
def VALIDATE_INPUTS(cls, **kwargs):
|
|
return True
|
|
|
|
def execute(self, variable_name, value, trigger=None, input=None):
|
|
v = input if input is not None else value
|
|
data = load_vars()
|
|
data[variable_name] = v
|
|
save_vars(data)
|
|
masked = _masked_summary(load_vars())
|
|
json_result = json.dumps({"node": "StringVarSetNode", "variable": variable_name, "value": v, "type": "string"})
|
|
return {"ui": {"text": [masked]}, "result": (v, json_result, "done")}
|
|
|
|
|
|
# ── STRING GET ────────────────────────────────────────
|
|
class StringVarGetNode:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"variable_name": ("STRING", {"default": "api_key"}),
|
|
},
|
|
"optional": {
|
|
"trigger": ("TRIGGER",),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING", "AUGMENT_JSON", "TRIGGER")
|
|
RETURN_NAMES = ("text", "json_result", "trigger")
|
|
FUNCTION = "execute"
|
|
CATEGORY = "Augment/Utils"
|
|
OUTPUT_NODE = True
|
|
|
|
@classmethod
|
|
def VALIDATE_INPUTS(cls, **kwargs):
|
|
return True
|
|
|
|
def execute(self, variable_name, trigger=None):
|
|
data = load_vars()
|
|
value = data.get(variable_name, "")
|
|
masked = _masked_summary(data)
|
|
json_result = json.dumps({"node": "StringVarGetNode", "variable": variable_name, "value": value, "type": "string"})
|
|
return {"ui": {"text": [masked]}, "result": (value, json_result, "done")}
|
|
|
|
|
|
# ── STRING DELETE ─────────────────────────────────────
|
|
class StringVarDeleteNode:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"variable_name": ("STRING", {"default": "api_key"}),
|
|
},
|
|
"optional": {
|
|
"trigger": ("TRIGGER",),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING", "AUGMENT_JSON", "TRIGGER")
|
|
RETURN_NAMES = ("text", "json_result", "trigger")
|
|
FUNCTION = "execute"
|
|
CATEGORY = "Augment/Utils"
|
|
OUTPUT_NODE = True
|
|
|
|
@classmethod
|
|
def VALIDATE_INPUTS(cls, **kwargs):
|
|
return True
|
|
|
|
def execute(self, variable_name, trigger=None):
|
|
data = load_vars()
|
|
removed = data.pop(variable_name, "")
|
|
save_vars(data)
|
|
json_result = json.dumps({"node": "StringVarDeleteNode", "variable": variable_name, "deleted_value": removed, "type": "string"})
|
|
return {"ui": {"text": [vars_summary()]}, "result": (removed, json_result, "done")}
|
|
|
|
|
|
# ── helpers ──────────────────────────────────────────
|
|
def _masked_summary(data):
|
|
"""Mask string values that look like keys/secrets in the UI."""
|
|
lines = []
|
|
for k, v in data.items():
|
|
if isinstance(v, str) and len(v) > 12:
|
|
lines.append(f"{k}: {v[:4]}...{v[-4:]}")
|
|
else:
|
|
lines.append(f"{k}: {v}")
|
|
return "\n".join(lines) if lines else "(no variables saved)"
|
|
|
|
|
|
NODE_CLASS_MAPPINGS = {
|
|
"NumberVarSetNode": NumberVarSetNode,
|
|
"NumberVarGetNode": NumberVarGetNode,
|
|
"NumberVarIncrementNode": NumberVarIncrementNode,
|
|
"NumberVarDecrementNode": NumberVarDecrementNode,
|
|
"NumberVarResetNode": NumberVarResetNode,
|
|
"StringVarSetNode": StringVarSetNode,
|
|
"StringVarGetNode": StringVarGetNode,
|
|
"StringVarDeleteNode": StringVarDeleteNode,
|
|
}
|
|
|
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
"NumberVarSetNode": "Variable Set (Number)",
|
|
"NumberVarGetNode": "Variable Get (Number)",
|
|
"NumberVarIncrementNode": "Variable Increment (Number)",
|
|
"NumberVarDecrementNode": "Variable Decrement (Number)",
|
|
"NumberVarResetNode": "Variable Reset (Number)",
|
|
"StringVarSetNode": "Variable Set (String)",
|
|
"StringVarGetNode": "Variable Get (String)",
|
|
"StringVarDeleteNode": "Variable Delete (String)",
|
|
} |