MOTORES: pastillas configurables y destino (salida o capa)
Las pestanas de capa de la barra superior no valian: mezclaban navegar por el panel con elegir sobre que se trabaja, y sacaban del panel de directo. Se quitan y todo pasa a MOTORES, con dos decisiones separadas: DONDE -> fila 'Donde se ve': SALIDA o una capa del mapping (+ crea una). QUE -> las pastillas: combinaciones guardadas por el usuario. Pinchar una pastilla la manda al destino elegido: con SALIDA cambia el motor global, con una capa cambia SOLO esa capa y el resto sigue igual. Con una capa elegida sus ajustes salen en MOTORES (la tarjeta de propiedades se mueve, no se duplica: dos formularios para lo mismo se desincronizan a la primera). Las pastillas son configurables: motor + preset + ajustes y su nombre, con 'Configurar pastillas'. Persisten en data/slots.json (gitignorado, es de cada instalacion). De fabrica vienen los cinco motores de siempre, asi que quien actualice se encuentra lo mismo que tenia. Hydra, Mezcla y projectM nativo solo pueden ir a la salida, y al intentar mandarlos a una capa se dice. Comprobado en Chromium por CDP, no con --dump-dom: ese fotografia el DOM al cargar, antes de que llegue el estado por socket, y daba falsos "esta vacio". Verificado que disparar sobre una capa deja el motor global intacto, que la tarjeta de propiedades va y vuelve de su sitio, y que las pastillas nuevas se guardan en disco. De paso, dos fallos que aparecieron al probarlo: - Restaurar la vista guardada corria al principio del fichero y llamaba a codigo que usa variables declaradas con let mas abajo: ReferenceError que se llevaba por delante el resto del script (socket incluido) y dejaba el panel en blanco. Ahora se restaura al final. - #card-destino no estaba en la lista de 'order' del CSS, asi que caia a 0 y se colaba encima de las pastillas pese a ir despues en el HTML. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f017246f0e
commit
61543e1987
8 changed files with 602 additions and 146 deletions
|
|
@ -79,6 +79,19 @@ socketio = SocketIO(app, async_mode="threading", cors_allowed_origins=None)
|
|||
HYDRA_SKETCHES = load_json(DATA / "hydra-sketches.json", {})
|
||||
SHADERS = load_json(DATA / "shaders.json", {})
|
||||
|
||||
# Pastillas: combinaciones guardadas (motor + preset + ajustes) que el panel
|
||||
# dispara de un toque sobre el destino elegido (la salida o una capa del
|
||||
# mapping). Las de fabrica son los cinco motores de siempre, para que quien
|
||||
# actualice se encuentre lo mismo que tenia.
|
||||
SLOTS_FABRICA = [
|
||||
{"id": "sl-projectm", "nombre": "projectM", "tipo": "projectm-nativo"},
|
||||
{"id": "sl-butter", "nombre": "Butter", "tipo": "butter",
|
||||
"biblioteca": "butter", "preset": ""},
|
||||
{"id": "sl-hydra", "nombre": "Hydra", "tipo": "hydra"},
|
||||
{"id": "sl-shaders", "nombre": "Shaders", "tipo": "shader", "shader": ""},
|
||||
{"id": "sl-mezcla", "nombre": "Mezcla", "tipo": "mixer"},
|
||||
]
|
||||
|
||||
DEFAULTS = CFG.get("defaults", {})
|
||||
ENGINES = ("projectm", "butterchurn", "hydra", "shaders", "mixer")
|
||||
|
||||
|
|
@ -187,6 +200,9 @@ state = {
|
|||
# apagado para que el proyector salga limpio, sin marcos
|
||||
# de colores ni circulos en las esquinas.
|
||||
edit=False),
|
||||
# Pastillas del panel: persisten en data/slots.json
|
||||
"slots": (load_json(DATA / "slots.json", None)
|
||||
if (DATA / "slots.json").is_file() else None) or list(SLOTS_FABRICA),
|
||||
"meta": {
|
||||
"butterchurnPresets": [],
|
||||
"audioDevices": [],
|
||||
|
|
@ -743,6 +759,34 @@ def capas_saneadas(lista, clave_geo):
|
|||
return limpio
|
||||
|
||||
|
||||
def slots_saneadas(lista):
|
||||
"""Filtra lo que no tenga forma de pastilla y limita cuantas se aceptan:
|
||||
igual que con el mapping, cualquiera en la red podria llenar el disco."""
|
||||
limpio = []
|
||||
for it in lista[:24]:
|
||||
if isinstance(it, dict) and isinstance(it.get("id"), str) \
|
||||
and isinstance(it.get("tipo"), str):
|
||||
it["nombre"] = str(it.get("nombre", ""))[:12]
|
||||
limpio.append(it)
|
||||
return limpio
|
||||
|
||||
|
||||
@socketio.on("set_slots")
|
||||
def on_set_slots(data):
|
||||
"""Guarda las pastillas del panel (data/slots.json) y las difunde."""
|
||||
lista = (data or {}).get("slots")
|
||||
if not isinstance(lista, list):
|
||||
return
|
||||
with lock:
|
||||
state["slots"] = slots_saneadas(lista)
|
||||
try:
|
||||
with open(DATA / "slots.json", "w", encoding="utf-8") as fh:
|
||||
json.dump(state["slots"], fh, ensure_ascii=False, indent=2)
|
||||
except OSError as exc:
|
||||
notify("error", f"No se pudieron guardar las pastillas: {exc}")
|
||||
broadcast()
|
||||
|
||||
|
||||
@socketio.on("set_mapping")
|
||||
def on_set_mapping(data):
|
||||
"""Projection mapping: activar/editar y guardar las superficies.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue