From 0bda2e1fb2dd5edf564446be2d24f18c11bc89e4 Mon Sep 17 00:00:00 2001 From: Pythza Date: Fri, 20 Feb 2026 21:09:04 +0100 Subject: [PATCH] Add files via upload --- README.md | 26 +++--------- __init__.py | 113 ++------------------------------------------------- js/pythza.js | 33 --------------- 3 files changed, 8 insertions(+), 164 deletions(-) diff --git a/README.md b/README.md index 4045184..50bb5c5 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ # ComfyUI-Pythza -A small collection of utility nodes for [ComfyUI](https://github.com/comfyanonymous/ComfyUI). +A small utility node for [ComfyUI](https://github.com/comfyanonymous/ComfyUI). -## Nodes +## 🧭 Node Navigator -### 🧭 Node Navigator Pan the canvas to any node by its ID. Useful for large workflows where you need to jump between distant nodes quickly. - Enter a **node ID** and click **"Go to node"** @@ -13,36 +12,21 @@ Pan the canvas to any node by its ID. Useful for large workflows where you need > **Tip:** You can find a node's ID by right-clicking it in ComfyUI — it's shown at the top of the context menu. -### 🎨 LoRA Formatter -Parses a LoRA tag string (e.g. ``) and displays a clean, readable preview. - -- Strips common prefixes like `SDXL_`, `PONY_`, etc. -- Shows up to 3 LoRA blocks with labels (Custom, Slider, Detail) -- Live preview widget on the node itself - -### 🔢 Count True Booleans -Counts how many of the connected boolean inputs are `True`. Accepts up to 20 optional boolean inputs. - -Handy for conditional logic — e.g. "run this branch only if at least 3 options are enabled." - ## Installation ### Manual ```bash cd ComfyUI/custom_nodes -git clone https://github.com/YOUR_USERNAME/ComfyUI-Pythza.git +git clone https://github.com/Pythza/ComfyUI-Pythza.git ``` Restart ComfyUI. -### ComfyUI Manager -Search for **Pythza** in the ComfyUI Manager install menu (once registered). - ## Structure ``` ComfyUI-Pythza/ -├── __init__.py # Node definitions (Python) +├── __init__.py # Node definition (Python) ├── js/ -│ └── pythza.js # Frontend (canvas navigation + LoRA preview widget) +│ └── pythza.js # Frontend (canvas navigation) └── README.md ``` diff --git a/__init__.py b/__init__.py index e05888d..dafe411 100644 --- a/__init__.py +++ b/__init__.py @@ -2,114 +2,11 @@ ComfyUI-Pythza — Utility nodes for ComfyUI https://github.com/Pythza/ComfyUI-Pythza """ -import re WEB_DIRECTORY = "./js" -# ── Helpers ─────────────────────────────────────────────────────────────────── - -STRIP_PREFIXES = ["SDXL_PONY_", "PONY_SDXL_", "SDXL_", "PONY_", "_SDXL_", "_PONY_"] -BLOCK_LABELS = ["Custom", "Slider", "Detail"] - - -def strip_prefix(name): - for prefix in STRIP_PREFIXES: - if name.upper().startswith(prefix.upper()): - return name[len(prefix):] - return name - - -def parse_lora(entry, label): - entry = entry.strip() - if not entry: - return None - match = re.match(r']+)>', entry) - if not match: - return None - inner = match.group(1) - parts = inner.rsplit(":", 1) - if len(parts) != 2: - return None - path, strength = parts[0].strip(), parts[1].strip() - filename = path.replace("\\", "/").split("/")[-1] - filename = re.sub(r'\.safetensors$', '', filename, flags=re.IGNORECASE) - clean = strip_prefix(filename) - return f"{label}: {clean}\nStrength: {strength}" - - -def format_lora_string(lora_string): - top_level = [] - depth = 0 - current = [] - for ch in lora_string: - if ch == "<": - depth += 1 - elif ch == ">": - depth -= 1 - if ch == "," and depth == 0: - top_level.append("".join(current).strip()) - current = [] - else: - current.append(ch) - top_level.append("".join(current).strip()) - - lines = [] - for i, block in enumerate(top_level[:3]): - label = BLOCK_LABELS[i] if i < len(BLOCK_LABELS) else f"Block{i+1}" - parsed = parse_lora(block, label) - if parsed: - if lines: - lines.append("") - lines.append(parsed) - - return "\n".join(lines) if lines else "(no LoRAs)" - - -# ── Node 1: LoRA Formatter ─────────────────────────────────────────────────── - -class PythzaLoraFormatter: - """Parses a LoRA tag string and displays a clean formatted preview.""" - - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "lora_string": ("STRING", {"forceInput": True}), - } - } - - RETURN_TYPES = ("STRING",) - RETURN_NAMES = ("formatted",) - FUNCTION = "format" - CATEGORY = "Pythza" - OUTPUT_NODE = True - - def format(self, lora_string): - result = format_lora_string(lora_string) - return {"ui": {"text": [result]}, "result": (result,)} - - -# ── Node 2: Count True Booleans ────────────────────────────────────────────── - -class PythzaCountTrue: - """Counts how many of the connected boolean inputs are True.""" - - @classmethod - def INPUT_TYPES(cls): - optional = {f"bool_{i}": ("BOOLEAN", {"default": False}) for i in range(1, 21)} - return {"required": {}, "optional": optional} - - RETURN_TYPES = ("INT",) - RETURN_NAMES = ("true_count",) - FUNCTION = "count" - CATEGORY = "Pythza" - - def count(self, **kwargs): - return (sum(1 for v in kwargs.values() if v is True),) - - -# ── Node 3: Node Navigator ────────────────────────────────────────────────── +# ── Node Navigator ─────────────────────────────────────────────────────────── class PythzaNodeNavigator: """UI-only node with a button that pans the canvas to a target node by ID.""" @@ -134,15 +31,11 @@ class PythzaNodeNavigator: # ── Registration ───────────────────────────────────────────────────────────── NODE_CLASS_MAPPINGS = { - "PythzaLoraFormatter": PythzaLoraFormatter, - "PythzaCountTrue": PythzaCountTrue, - "PythzaNodeNavigator": PythzaNodeNavigator, + "PythzaNodeNavigator": PythzaNodeNavigator, } NODE_DISPLAY_NAME_MAPPINGS = { - "PythzaLoraFormatter": "LoRA Formatter (Pythza)", - "PythzaCountTrue": "Count True Booleans (Pythza)", - "PythzaNodeNavigator": "Node Navigator (Pythza)", + "PythzaNodeNavigator": "Node Navigator (Pythza)", } __all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS', 'WEB_DIRECTORY'] diff --git a/js/pythza.js b/js/pythza.js index 859e940..4f3cb72 100644 --- a/js/pythza.js +++ b/js/pythza.js @@ -35,36 +35,3 @@ app.registerExtension({ }; } }); - -// ── LoRA Formatter ────────────────────────────────────────────────────────── -app.registerExtension({ - name: "Pythza.LoraFormatter", - - async beforeRegisterNodeDef(nodeType, nodeData) { - if (nodeData.name !== "PythzaLoraFormatter") return; - - const origOnNodeCreated = nodeType.prototype.onNodeCreated; - nodeType.prototype.onNodeCreated = function () { - if (origOnNodeCreated) origOnNodeCreated.apply(this, arguments); - - const textWidget = this.addWidget("text", "preview", "", () => {}, { - multiline: true, - readonly: true, - }); - textWidget.inputEl?.setAttribute("readonly", true); - this._previewWidget = textWidget; - this.setSize([300, 200]); - }; - - const origOnExecuted = nodeType.prototype.onExecuted; - nodeType.prototype.onExecuted = function (message) { - if (origOnExecuted) origOnExecuted.apply(this, arguments); - if (message?.text?.[0] !== undefined && this._previewWidget) { - this._previewWidget.value = message.text[0]; - const lines = message.text[0].split("\n").length; - this.setSize([300, Math.max(120, 40 + lines * 20)]); - this.setDirtyCanvas(true); - } - }; - } -});