Mapping Fase 2: malla deformable (superficies curvas) + mascaras

- Superficies con rejilla n x n (hasta 6x6): arrastra cualquier punto para
  curvar, no solo las esquinas. Render perspectiva-correcto por celda
  (homografia cuadrado->celda).
- Mascaras: cuadrilateros negros que tapan zonas / recortan derrames de luz.
- Editable desde la previsualizacion del panel (raton/tactil) y el escenario:
  arrastrar puntos, +/- malla para subdividir, borrar por lista.
- set_mapping acepta "masks"; persiste en data/mapping.json (ignorado en git).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
hacklab 2026-07-27 00:40:43 +02:00
parent 8dd58bb293
commit 7c0be6b666
4 changed files with 460 additions and 334 deletions

View file

@ -153,7 +153,8 @@ state = {
# surfaces = [{id, corners:[[x,y]x4]}] normalizado 0..1. Persiste en
# data/mapping.json.
"mapping": load_json(DATA / "mapping.json",
{"enabled": False, "edit": False, "surfaces": []}),
{"enabled": False, "edit": False,
"surfaces": [], "masks": []}),
"meta": {
"butterchurnPresets": [],
"audioDevices": [],
@ -639,6 +640,9 @@ def on_set_mapping(data):
m["edit"] = bool(data["edit"])
if "surfaces" in data and isinstance(data["surfaces"], list):
m["surfaces"] = data["surfaces"]
if "masks" in data and isinstance(data["masks"], list):
m["masks"] = data["masks"]
m.setdefault("masks", [])
save_mapping()
broadcast()