A preset was applied at execution time, so the panel lied: select explore and shader_strength kept showing its old value while the run used 0.30. web/src/preset_widgets.ts wraps the preset widget's callback and writes the bundle into the widgets it names, running each widget's own callback so the shader preview follows. Editing one of those widgets to a value the preset does not hold drops the preset back to custom -- otherwise the panel would just lie the other way. The Walk node keeps the parameter it ramps, and a saved workflow is never rewritten on load. The table comes from GET /shader_noise_ksampler/presets rather than a copy in TypeScript, because preset values get recalibrated and a copy would drift. The Python override stays the authority: API submissions and the Walk node never run the JS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
96 lines
3.4 KiB
Python
96 lines
3.4 KiB
Python
"""
|
|
API routes for ShaderNoiseKSampler extension.
|
|
|
|
Provides server-side endpoints for saving shader parameters from the frontend.
|
|
"""
|
|
|
|
from aiohttp import web
|
|
import json
|
|
import logging
|
|
import os
|
|
from .shader_params_reader import ShaderParamsReader
|
|
|
|
logger = logging.getLogger("ShaderNoiseKSampler")
|
|
|
|
# Get extension directory
|
|
EXTENSION_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
# Keys the save button sends. Anything else is dropped rather than persisted:
|
|
# the file is read back into shader params on every run, so unknown keys would
|
|
# flow into noise generation untouched by validate_and_sanitize_params.
|
|
ALLOWED_KEYS = frozenset({
|
|
"shaderType",
|
|
"shaderScale",
|
|
"shaderOctaves",
|
|
"shaderWarpStrength",
|
|
"shaderShapeType",
|
|
"shaderShapeStrength",
|
|
"shaderPhaseShift",
|
|
"colorScheme",
|
|
"shaderColorIntensity",
|
|
"visualization_type",
|
|
})
|
|
|
|
|
|
async def save_shader_params(request):
|
|
"""
|
|
API endpoint to save shader parameters to JSON file.
|
|
|
|
Receives JSON data from the frontend and writes it to data/shader_params.json.
|
|
This enables automatic parameter persistence without manual file downloads.
|
|
"""
|
|
try:
|
|
data = await request.json()
|
|
if not isinstance(data, dict):
|
|
return web.json_response(
|
|
{"status": "error", "message": "Expected a JSON object"}, status=400
|
|
)
|
|
|
|
params_file = os.path.join(EXTENSION_DIR, "data", "shader_params.json")
|
|
|
|
# Ensure data directory exists
|
|
os.makedirs(os.path.dirname(params_file), exist_ok=True)
|
|
|
|
# Keep only known keys, then validate and sanitize what is left
|
|
known = {key: value for key, value in data.items() if key in ALLOWED_KEYS}
|
|
sanitized_data = ShaderParamsReader.validate_and_sanitize_params(known)
|
|
|
|
with open(params_file, 'w') as f:
|
|
json.dump(sanitized_data, f, indent=2)
|
|
|
|
logger.info("Saved shader params to %s", params_file)
|
|
return web.json_response({"status": "success"})
|
|
except json.JSONDecodeError:
|
|
return web.json_response({"status": "error", "message": "Invalid JSON"}, status=400)
|
|
except Exception:
|
|
# Log the detail, but do not hand internals back to the caller
|
|
logger.exception("Error saving shader params")
|
|
return web.json_response({"status": "error", "message": "Could not save parameters"}, status=500)
|
|
|
|
|
|
async def get_presets(request):
|
|
"""
|
|
Serve the preset table, so the frontend can write a preset's values into the
|
|
widgets without keeping a copy of its own. Preset values get recalibrated
|
|
against real runs, and a second copy would drift the first time one did.
|
|
"""
|
|
from .core import presets
|
|
return web.json_response({
|
|
"presets": presets.PRESETS,
|
|
"descriptions": presets.PRESET_DESCRIPTIONS,
|
|
"keys": list(presets.PRESET_KEYS),
|
|
})
|
|
|
|
def setup_routes(server):
|
|
"""
|
|
Register API routes with ComfyUI's PromptServer.
|
|
|
|
Args:
|
|
server: The PromptServer instance from ComfyUI
|
|
"""
|
|
if hasattr(server, 'app') and hasattr(server.app, 'router'):
|
|
server.app.router.add_post("/shader_noise_ksampler/save_params", save_shader_params)
|
|
logger.info("Registered API route: POST /shader_noise_ksampler/save_params")
|
|
server.app.router.add_get("/shader_noise_ksampler/presets", get_presets)
|
|
logger.info("Registered API route: GET /shader_noise_ksampler/presets")
|