mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-02-02 17:50:19 +08:00
156 lines
4.9 KiB
Python
156 lines
4.9 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Shader Blueprint Updater
|
|
|
|
Syncs GLSL shader files between this folder and blueprint JSON files.
|
|
|
|
File naming convention:
|
|
{Blueprint Name}_{node_id}.frag
|
|
|
|
Usage:
|
|
python update_blueprints.py extract # Extract shaders from JSONs to here
|
|
python update_blueprints.py patch # Patch shaders back into JSONs
|
|
python update_blueprints.py # Same as patch (default)
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
import re
|
|
from pathlib import Path
|
|
|
|
GLSL_DIR = Path(__file__).parent
|
|
BLUEPRINTS_DIR = GLSL_DIR.parent
|
|
|
|
|
|
def get_blueprint_files():
|
|
"""Get all blueprint JSON files."""
|
|
return sorted(BLUEPRINTS_DIR.glob("*.json"))
|
|
|
|
|
|
def sanitize_filename(name):
|
|
"""Convert blueprint name to safe filename."""
|
|
return re.sub(r'[^\w\-]', '_', name)
|
|
|
|
|
|
def extract_shaders():
|
|
"""Extract all shaders from blueprint JSONs to this folder."""
|
|
extracted = 0
|
|
for json_path in get_blueprint_files():
|
|
blueprint_name = json_path.stem
|
|
|
|
try:
|
|
with open(json_path, 'r') as f:
|
|
data = json.load(f)
|
|
except (json.JSONDecodeError, IOError) as e:
|
|
print(f" Skipping {json_path.name}: {e}")
|
|
continue
|
|
|
|
# Find GLSLShader nodes in subgraphs
|
|
for subgraph in data.get('definitions', {}).get('subgraphs', []):
|
|
for node in subgraph.get('nodes', []):
|
|
if node.get('type') == 'GLSLShader':
|
|
node_id = node.get('id')
|
|
widgets = node.get('widgets_values', [])
|
|
|
|
# Find shader code (first string that looks like GLSL)
|
|
for widget in widgets:
|
|
if isinstance(widget, str) and widget.startswith('#version'):
|
|
safe_name = sanitize_filename(blueprint_name)
|
|
frag_name = f"{safe_name}_{node_id}.frag"
|
|
frag_path = GLSL_DIR / frag_name
|
|
|
|
with open(frag_path, 'w') as f:
|
|
f.write(widget)
|
|
|
|
print(f" Extracted: {frag_name}")
|
|
extracted += 1
|
|
break
|
|
|
|
print(f"\nExtracted {extracted} shader(s)")
|
|
|
|
|
|
def patch_shaders():
|
|
"""Patch shaders from this folder back into blueprint JSONs."""
|
|
# Build lookup: blueprint_name -> [(node_id, shader_code), ...]
|
|
shader_updates = {}
|
|
|
|
for frag_path in sorted(GLSL_DIR.glob("*.frag")):
|
|
# Parse filename: {blueprint_name}_{node_id}.frag
|
|
parts = frag_path.stem.rsplit('_', 1)
|
|
if len(parts) != 2:
|
|
print(f" Skipping {frag_path.name}: invalid filename format")
|
|
continue
|
|
|
|
blueprint_name, node_id_str = parts
|
|
|
|
try:
|
|
node_id = int(node_id_str)
|
|
except ValueError:
|
|
print(f" Skipping {frag_path.name}: invalid node_id")
|
|
continue
|
|
|
|
with open(frag_path, 'r') as f:
|
|
shader_code = f.read()
|
|
|
|
if blueprint_name not in shader_updates:
|
|
shader_updates[blueprint_name] = []
|
|
shader_updates[blueprint_name].append((node_id, shader_code))
|
|
|
|
# Apply updates to JSON files
|
|
patched = 0
|
|
for json_path in get_blueprint_files():
|
|
blueprint_name = sanitize_filename(json_path.stem)
|
|
|
|
if blueprint_name not in shader_updates:
|
|
continue
|
|
|
|
try:
|
|
with open(json_path, 'r') as f:
|
|
data = json.load(f)
|
|
except (json.JSONDecodeError, IOError) as e:
|
|
print(f" Error reading {json_path.name}: {e}")
|
|
continue
|
|
|
|
modified = False
|
|
for node_id, shader_code in shader_updates[blueprint_name]:
|
|
# Find the node and update
|
|
for subgraph in data.get('definitions', {}).get('subgraphs', []):
|
|
for node in subgraph.get('nodes', []):
|
|
if node.get('id') == node_id and node.get('type') == 'GLSLShader':
|
|
widgets = node.get('widgets_values', [])
|
|
if len(widgets) > 0 and widgets[0] != shader_code:
|
|
widgets[0] = shader_code
|
|
modified = True
|
|
print(f" Patched: {json_path.name} (node {node_id})")
|
|
patched += 1
|
|
|
|
if modified:
|
|
with open(json_path, 'w') as f:
|
|
json.dump(data, f)
|
|
|
|
if patched == 0:
|
|
print("No changes to apply.")
|
|
else:
|
|
print(f"\nPatched {patched} shader(s)")
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) < 2:
|
|
command = "patch"
|
|
else:
|
|
command = sys.argv[1].lower()
|
|
|
|
if command == "extract":
|
|
print("Extracting shaders from blueprints...")
|
|
extract_shaders()
|
|
elif command in ("patch", "update", "apply"):
|
|
print("Patching shaders into blueprints...")
|
|
patch_shaders()
|
|
else:
|
|
print(__doc__)
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|