Capas independientes, projectM en el mapping y catalogo de la galeria
Mapping - Los clips salian del reves: mapper.js activaba UNPACK_FLIP_Y_WEBGL, pero el modelo va con origen arriba-izquierda y texImage2D ya sube la primera fila en t=0, asi que el flip la mandaba al final. Comprobado renderizando el mapper real en Chromium headless con una fuente mitad roja / mitad azul. - projectM se puede usar YA en una capa: los .milk de data/presets-projectm se traducen a Butterchurn en el navegador al elegirlos (milkdrop-preset- converter). La capa MilkDrop gana 'biblioteca' (butter | projectm) sin cambiar su firma, para no recrear el contexto WebGL al cambiar de una a otra. Medido: 100/100 presets de una muestra convierten, 84/84 de los que llevan shaders warp/comp; ~7 ms por preset. - Cada capa tiene su pestana arriba y su propia vista, y '+ CAPA' crea una y entra en ella: con varias capas, ir y volver a MAPPING no era viable. - Dos capas MilkDrop sin preset ya no salen identicas (cogian el indice 0): cada instancia elige uno al azar y lo escribe en el estado. - Una capa nueva ya no nace en la fuente "motor", que es el lienzo del motor activo y hacia que dos capas ensenaran lo mismo. Galeria de visuales - scripts/catalogar-visuales.py: ficha de cada clip (pelicula, personajes, duracion) y, sobre todo, si es una silueta de verdad y cuanta figura tiene. Distingue silueta de corte crudo por el negro puro del fondo: 0,63-0,90 frente a 0,04-0,06, sin zona gris. - El panel lista los clips agrupados por pelicula, con nombre legible y aviso de los que casi no tienen figura, en vez del nombre del archivo. - Soporte de siluetas con canal alfa (.webm VP9): transparencia de verdad, sin recorte por luminancia. El shader del mapper ya la respeta. Documentacion - docs/visuales.md nuevo; pendiente.md al dia con lo hecho y lo que queda. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5d5223db9f
commit
f017246f0e
30 changed files with 3771 additions and 292 deletions
|
|
@ -9,15 +9,33 @@
|
|||
<link rel="stylesheet" href="/lib/codemirror/material-darker.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>FOSFENO</h1>
|
||||
<span id="conn" class="dot off" title="Conexion"></span>
|
||||
</header>
|
||||
<!-- Barra superior fija: titulo + pestanas + banda de avisos.
|
||||
Van juntas en un mismo bloque sticky para que el aviso quede siempre
|
||||
pegado debajo del titulo, aunque las pestanas salten de linea. -->
|
||||
<div class="topbar">
|
||||
<header>
|
||||
<h1>FOSFENO</h1>
|
||||
<!-- Dos zonas del panel: MOTORES (lo de siempre) y MAPPING (aparte,
|
||||
para que no se mezclen los controles de directo con los de
|
||||
encaje sobre la superficie fisica). -->
|
||||
<nav class="tabs" id="tabs">
|
||||
<button class="tab active" data-view="motores">MOTORES</button>
|
||||
<button class="tab" data-view="mapping">MAPPING<span
|
||||
id="tab-map-dot" class="tabdot" hidden></span></button>
|
||||
<!-- Una pestana por capa del mapping: se generan solas (renderTabsCapas)
|
||||
para poder saltar a editar cada capa sin pasar por MAPPING -->
|
||||
<span id="tabs-capas"></span>
|
||||
<button class="tab tabnew" id="tab-nueva-capa"
|
||||
title="Crear una capa nueva y abrirla">+ CAPA</button>
|
||||
</nav>
|
||||
<span id="conn" class="dot off" title="Conexion"></span>
|
||||
</header>
|
||||
|
||||
<!-- Banda de avisos: aqui aparece cualquier error o aviso -->
|
||||
<div id="notif" class="notif" hidden>
|
||||
<span id="notif-msg"></span>
|
||||
<button id="notif-close" aria-label="Cerrar aviso">×</button>
|
||||
<!-- Banda de avisos: aqui aparece cualquier error o aviso -->
|
||||
<div id="notif" class="notif" hidden>
|
||||
<span id="notif-msg"></span>
|
||||
<button id="notif-close" aria-label="Cerrar aviso">×</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- En movil las tarjetas van en una sola columna; en pantalla ancha,
|
||||
|
|
@ -148,38 +166,69 @@
|
|||
<p class="hint" id="editor-hint"></p>
|
||||
</section>
|
||||
|
||||
<!-- Mezclador VJ -->
|
||||
<!-- Mezclador VJ.
|
||||
Se lee de arriba abajo como dos capas: el FONDO (capa de abajo:
|
||||
camara o visuales Butter) y el CLIP de la galeria (capa de
|
||||
encima), mas la forma de juntarlos. El resumen de mas abajo
|
||||
dice en una linea que va a salir por el proyector. -->
|
||||
<section class="card" id="ctl-mixer" hidden>
|
||||
<div class="cardhead">
|
||||
<span class="label">Mezclador VJ</span>
|
||||
<button class="info" data-help="mixer">i</button>
|
||||
</div>
|
||||
|
||||
<!-- 1. Que se ve -->
|
||||
<span class="label">1 · Que se ve</span>
|
||||
<div class="seg" id="mixer-source">
|
||||
<button class="segbtn" data-src="cam">Camara</button>
|
||||
<button class="segbtn" data-src="video">Video</button>
|
||||
<button class="segbtn" data-src="mix">Mezcla</button>
|
||||
<button class="segbtn" data-src="cam">Solo el fondo</button>
|
||||
<button class="segbtn" data-src="video">Solo el clip</button>
|
||||
<button class="segbtn" data-src="mix">Los dos</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<span class="label">Fondo (capa de abajo)</span>
|
||||
|
||||
<!-- 2. Fondo: capa de abajo -->
|
||||
<div class="row" id="mix-fondo-row">
|
||||
<span class="label">2 · Fondo (capa de abajo)</span>
|
||||
<select id="mix-fondo" class="inline">
|
||||
<option value="cam">Camara</option>
|
||||
<option value="butter">Visuales Butter (MilkDrop)</option>
|
||||
</select>
|
||||
</div>
|
||||
<label class="check">
|
||||
<input type="checkbox" id="mix-cam"> Camara activada
|
||||
</label>
|
||||
<select id="mix-camera"><option value="0">Camara por defecto</option></select>
|
||||
<!-- Fondo = camara -->
|
||||
<div class="stack" id="mix-cam-block">
|
||||
<label class="check">
|
||||
<input type="checkbox" id="mix-cam"> Camara activada
|
||||
</label>
|
||||
<select id="mix-camera"><option value="0">Camara por defecto</option></select>
|
||||
</div>
|
||||
<!-- Fondo = visuales Butter: se elige aqui mismo el preset de
|
||||
MilkDrop que hace de fondo, sin salir del mezclador. -->
|
||||
<div class="stack" id="mix-bg-block" hidden>
|
||||
<select id="mix-bg-preset"><option>Cargando presets...</option></select>
|
||||
<div class="row">
|
||||
<button id="mix-bg-prev" class="cmd">« Anterior</button>
|
||||
<button id="mix-bg-next" class="cmd">Siguiente »</button>
|
||||
</div>
|
||||
<label class="check">
|
||||
<input type="checkbox" id="mix-bg-shuffle"> Cambiar el fondo solo
|
||||
</label>
|
||||
<p class="hint">Es el mismo preset y el mismo cambio automatico del
|
||||
motor Butter: lo que elijas aqui queda elegido tambien alli.</p>
|
||||
</div>
|
||||
|
||||
<!-- 3. Clip de la galeria: capa de encima -->
|
||||
<span class="label" id="mix-clip-label">3 · Clip (capa de encima)</span>
|
||||
<select id="mix-video"><option value="">-- sin video --</option></select>
|
||||
<div class="row">
|
||||
<button id="mix-rescan" class="cmd">Actualizar lista</button>
|
||||
<button id="mix-upload-btn" class="cmd">Subir video o imagen</button>
|
||||
<span id="mix-upload-status" class="hint"></span>
|
||||
</div>
|
||||
<span id="mix-upload-status" class="hint"></span>
|
||||
<input type="file" id="mix-upload" hidden
|
||||
accept="video/*,image/jpeg,image/png,image/gif,image/webp">
|
||||
<div class="row">
|
||||
<span class="label">Modo de mezcla</span>
|
||||
|
||||
<!-- 4. Como se juntan las dos capas -->
|
||||
<div class="row" id="mix-blend-row">
|
||||
<span class="label">4 · Como se juntan</span>
|
||||
<select id="mix-blend" class="inline">
|
||||
<option value="recorte">Recorte (personaje delante)</option>
|
||||
<option value="blend">Fundido</option>
|
||||
|
|
@ -189,6 +238,10 @@
|
|||
<option value="layer">Capa</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Resumen en una linea de lo que sale por el proyector -->
|
||||
<p class="hint resumen" id="mix-resumen"></p>
|
||||
|
||||
<div id="mixer-sliders"></div>
|
||||
<label class="check">
|
||||
<input type="checkbox" id="mix-invert"> Invertir colores
|
||||
|
|
@ -248,37 +301,165 @@
|
|||
deslizador relanza projectM (~1 s en negro).</p>
|
||||
</section>
|
||||
|
||||
<!-- Mapping (projection mapping) -->
|
||||
<section class="card" id="card-mapping">
|
||||
<!-- ===================== PESTANA MAPPING ===================== -->
|
||||
|
||||
<!-- Salida: encendido y previsualizacion -->
|
||||
<section class="card" id="card-mapping" data-vista="mapping">
|
||||
<div class="cardhead">
|
||||
<span class="label">Mapping</span>
|
||||
<button class="info" data-help="mapping">i</button>
|
||||
</div>
|
||||
<label class="check">
|
||||
<input type="checkbox" id="map-enabled"> Activar mapping
|
||||
</label>
|
||||
<label class="check">
|
||||
<input type="checkbox" id="map-edit"> Modo edicion (arrastrar en el escenario)
|
||||
</label>
|
||||
<div class="row">
|
||||
<button id="map-add" class="cmd accent">+ Superficie</button>
|
||||
<label class="check">
|
||||
<input type="checkbox" id="map-enabled"> Activar mapping
|
||||
</label>
|
||||
<label class="check">
|
||||
<input type="checkbox" id="map-edit"> Editar en el escenario
|
||||
</label>
|
||||
</div>
|
||||
<span class="label">Previsualizacion (arrastra los puntos)</span>
|
||||
<canvas id="map-preview"></canvas>
|
||||
<p class="hint">Arrastra los puntos para encajar cada capa en su sitio.
|
||||
Toca dentro de una capa para seleccionarla. Se guarda solo.</p>
|
||||
</section>
|
||||
|
||||
<!-- Capas: la lista, al estilo de una mesa de VJ -->
|
||||
<section class="card" id="card-capas" data-vista="mapping">
|
||||
<div class="cardhead">
|
||||
<span class="label">Capas</span>
|
||||
<button class="info" data-help="capas">i</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button id="map-add" class="cmd accent">+ Capa</button>
|
||||
<button id="map-add-mask" class="cmd">+ Mascara</button>
|
||||
<button id="map-reset" class="cmd">Reset</button>
|
||||
</div>
|
||||
<span class="label">Previsualizacion (arrastra los puntos)</span>
|
||||
<canvas id="map-preview"
|
||||
style="width:100%;aspect-ratio:16/9;background:#0a0a0a;border:1px solid #333;border-radius:6px;display:block;margin:6px 0;touch-action:none;cursor:crosshair;"></canvas>
|
||||
<div class="row" id="map-selbar" hidden>
|
||||
<span class="label" id="map-selinfo">Superficie seleccionada</span>
|
||||
<button id="map-sub-dec" class="cmd">− malla</button>
|
||||
<span id="map-sub-val" class="value">1x1</span>
|
||||
<button id="map-sub-inc" class="cmd">+ malla</button>
|
||||
</div>
|
||||
<p class="hint"><b>Capa</b> = una zona que PROYECTA algo (eliges que en
|
||||
Propiedades). <b>Mascara</b> = un recuadro negro que TAPA lo que haya
|
||||
debajo; no lleva visual.</p>
|
||||
<div id="map-list"></div>
|
||||
<p class="hint">Arrastra los puntos para deformar. Selecciona una
|
||||
superficie y usa <b>+ malla</b> para subdividir y <b>curvarla</b>.
|
||||
<b>+ Mascara</b> tapa zonas con un recuadro negro (recorta derrames
|
||||
de luz). Se guarda solo.</p>
|
||||
<p class="hint" id="map-list-vacio">Sin capas: con el mapping activado
|
||||
y ninguna capa, sale el motor a pantalla completa. Pulsa
|
||||
<b>+ Capa</b> para trocear la proyeccion en zonas.</p>
|
||||
</section>
|
||||
|
||||
<!-- Propiedades de la capa seleccionada -->
|
||||
<section class="card" id="card-propiedades" data-vista="mapping">
|
||||
<div class="cardhead">
|
||||
<span class="label" id="prop-titulo">Propiedades</span>
|
||||
<button class="info" data-help="fuentes">i</button>
|
||||
</div>
|
||||
|
||||
<p class="hint" id="prop-vacio">Selecciona una capa (en la lista o
|
||||
tocando dentro de ella en la previsualizacion) para elegir que
|
||||
visual se proyecta en esa zona.</p>
|
||||
|
||||
<div class="stack" id="prop-capa" hidden>
|
||||
<div class="row">
|
||||
<span class="label">Nombre</span>
|
||||
<input type="text" id="prop-nombre" class="txt" maxlength="24"
|
||||
placeholder="Capa">
|
||||
</div>
|
||||
|
||||
<span class="label">Que se proyecta aqui</span>
|
||||
<select id="prop-fuente">
|
||||
<option value="motor">El motor elegido en MOTORES</option>
|
||||
<option value="butter">Visuales MilkDrop (propias de esta capa)</option>
|
||||
<option value="shader">Shader GLSL</option>
|
||||
<option value="video">Clip o imagen de la galeria</option>
|
||||
<option value="camara">Camara</option>
|
||||
<option value="negro">Negro (tapar)</option>
|
||||
</select>
|
||||
|
||||
<!-- Ajustes propios de cada fuente -->
|
||||
<div class="stack fuente-op" id="fop-butter" hidden>
|
||||
<span class="label">Biblioteca de presets</span>
|
||||
<select id="prop-biblioteca">
|
||||
<option value="butter">Butterchurn — ~100 presets, los mas ligeros</option>
|
||||
<option value="projectm">projectM — tu biblioteca .milk (9795)</option>
|
||||
</select>
|
||||
|
||||
<!-- Biblioteca de Butterchurn -->
|
||||
<div class="stack" id="fop-bib-butter">
|
||||
<select id="prop-preset"><option>Cargando presets...</option></select>
|
||||
<div class="row">
|
||||
<button id="prop-preset-prev" class="cmd">« Anterior</button>
|
||||
<button id="prop-preset-next" class="cmd">Siguiente »</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Biblioteca de projectM: los .milk se traducen al vuelo -->
|
||||
<div class="stack" id="fop-bib-milk" hidden>
|
||||
<select id="prop-milk-cat"><option value="">-- categoria --</option></select>
|
||||
<select id="prop-milk-vis"><option value="">-- visual --</option></select>
|
||||
<select id="prop-milk-var"><option value="">-- variante --</option></select>
|
||||
<button id="prop-milk-azar" class="cmd">Uno al azar</button>
|
||||
<p class="hint" id="prop-milk-est">Los .milk se traducen a
|
||||
Butterchurn en el propio navegador, al elegirlos. Alguno puede
|
||||
salir distinto al original: si uno no convence, prueba otra
|
||||
variante.</p>
|
||||
</div>
|
||||
|
||||
<label class="check">
|
||||
<input type="checkbox" id="prop-auto"> Cambiar de preset solo
|
||||
</label>
|
||||
<div class="row" id="prop-auto-row" hidden>
|
||||
<span class="label">Cada <span id="prop-seg-val" class="value">20</span> s</span>
|
||||
</div>
|
||||
<input id="prop-seg" type="range" min="3" max="180" step="1" value="20" hidden>
|
||||
<div class="row">
|
||||
<span class="label">Transicion:
|
||||
<span id="prop-tr-val" class="value">2.5</span> s</span>
|
||||
</div>
|
||||
<input id="prop-transicion" type="range" min="0" max="8" step="0.1" value="2.5">
|
||||
<p class="hint">A 0 el preset cambia de golpe; subiendolo, uno se
|
||||
disuelve en el siguiente sin que se note el corte.</p>
|
||||
</div>
|
||||
|
||||
<div class="stack fuente-op" id="fop-shader" hidden>
|
||||
<select id="prop-shader"><option value="">-- elige un shader --</option></select>
|
||||
</div>
|
||||
|
||||
<div class="stack fuente-op" id="fop-video" hidden>
|
||||
<select id="prop-video"><option value="">-- elige un clip --</option></select>
|
||||
</div>
|
||||
|
||||
<div class="stack fuente-op" id="fop-camara" hidden>
|
||||
<select id="prop-camara"><option value="0">Camara por defecto</option></select>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<span class="label">Opacidad: <span id="prop-op-val" class="value">100</span>%</span>
|
||||
</div>
|
||||
<input id="prop-opacidad" type="range" min="0" max="1" step="0.02" value="1">
|
||||
|
||||
<div class="row">
|
||||
<span class="label">Mezcla con lo de debajo</span>
|
||||
<select id="prop-mezcla" class="inline">
|
||||
<option value="normal">Normal (tapa)</option>
|
||||
<option value="sumar">Sumar (apila luz)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<span class="label">Malla (para curvar)</span>
|
||||
<span class="grupo">
|
||||
<button id="map-sub-dec" class="cmd">−</button>
|
||||
<span id="map-sub-val" class="value">1x1</span>
|
||||
<button id="map-sub-inc" class="cmd">+</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stack" id="prop-mascara" hidden>
|
||||
<p class="hint">Una mascara solo TAPA: es un recuadro negro que se
|
||||
pinta encima de todo, para recortar derrames de luz. No lleva
|
||||
visual, por eso aqui no hay nada que elegir. Arrastra sus esquinas
|
||||
en la previsualizacion.</p>
|
||||
<p class="hint resumen">Si lo que querias era proyectar algo en esta
|
||||
zona, eso es una <b>capa</b>, no una mascara.</p>
|
||||
<button id="mask-a-capa" class="cmd accent">Convertirla en capa</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -35,11 +35,17 @@ body {
|
|||
padding-bottom: 48px;
|
||||
}
|
||||
|
||||
/* --- Cabecera con el titulo centrado --- */
|
||||
/* --- Barra superior fija: titulo + pestanas + avisos --- */
|
||||
.topbar {
|
||||
position: sticky; top: 0; z-index: 10; background: var(--bg);
|
||||
}
|
||||
|
||||
/* --- Cabecera con el titulo centrado y las pestanas a su derecha --- */
|
||||
header {
|
||||
position: sticky; top: 0; z-index: 10;
|
||||
position: relative;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
padding: 16px 20px; border-bottom: 2px solid var(--green-d);
|
||||
flex-wrap: wrap; gap: 10px 20px;
|
||||
padding: 14px 46px; border-bottom: 2px solid var(--green-d);
|
||||
background: var(--bg);
|
||||
}
|
||||
header h1 {
|
||||
|
|
@ -50,6 +56,35 @@ header h1 {
|
|||
#conn {
|
||||
position: absolute; right: 20px; top: 50%; transform: translateY(-50%);
|
||||
}
|
||||
|
||||
/* --- Pestanas MOTORES / MAPPING --- */
|
||||
.tabs { display: flex; gap: 8px; }
|
||||
.tab {
|
||||
position: relative; cursor: pointer;
|
||||
font-family: "Xirod", "Arial Black", sans-serif;
|
||||
font-size: 12px; font-weight: 400; letter-spacing: 0.07em;
|
||||
padding: 10px 15px; border-radius: 10px;
|
||||
background: #161d10; border: 2px solid var(--line); color: var(--dim);
|
||||
}
|
||||
.tab.active {
|
||||
border-color: var(--orange); color: var(--orange-n);
|
||||
box-shadow: 0 0 12px rgba(255, 122, 0, 0.35);
|
||||
}
|
||||
/* Punto verde en la pestana MAPPING cuando el mapping esta activado, para
|
||||
saber desde MOTORES que la salida se esta deformando. */
|
||||
.tabdot {
|
||||
display: inline-block; width: 8px; height: 8px; border-radius: 50%;
|
||||
background: var(--green); box-shadow: 0 0 8px var(--green);
|
||||
margin-left: 7px; vertical-align: middle;
|
||||
}
|
||||
|
||||
/* En movil el titulo baja de tamano para que las pestanas quepan al lado */
|
||||
@media (max-width: 560px) {
|
||||
header { padding: 12px 34px; gap: 8px 12px; }
|
||||
header h1 { font-size: 23px; }
|
||||
.tab { padding: 9px 11px; font-size: 11px; }
|
||||
#conn { right: 12px; }
|
||||
}
|
||||
.dot { width: 13px; height: 13px; border-radius: 50%; display: inline-block; }
|
||||
.dot.on { background: var(--green); box-shadow: 0 0 9px var(--green); }
|
||||
.dot.off { background: var(--red); box-shadow: 0 0 9px var(--red); }
|
||||
|
|
@ -82,6 +117,61 @@ main {
|
|||
}
|
||||
}
|
||||
|
||||
/* --- Vistas (pestanas) ---
|
||||
MOTORES ensena todo menos las tarjetas de mapping, y al reves. La vista
|
||||
"capa" es MAPPING recortado: solo la previa y las propiedades de UNA capa,
|
||||
sin la lista, para poder centrarse en su efecto. */
|
||||
body[data-view="motores"] [data-vista="mapping"] { display: none !important; }
|
||||
body[data-view="mapping"] main > .column > :not([data-vista="mapping"]),
|
||||
body[data-view="capa"] main > .column > :not([data-vista="mapping"]) {
|
||||
display: none !important;
|
||||
}
|
||||
body[data-view="capa"] #card-capas { display: none !important; }
|
||||
body[data-view="mapping"] main,
|
||||
body[data-view="capa"] main {
|
||||
flex-direction: column; width: 100%; max-width: 900px;
|
||||
}
|
||||
body[data-view="mapping"] .column,
|
||||
body[data-view="capa"] .column { display: contents; }
|
||||
|
||||
/* Pestanas de capa: mas pequenas que MOTORES/MAPPING, para que se lean como
|
||||
lo que son (un atajo a cada capa) y no compitan con las dos principales. */
|
||||
.tab.tabcapa, .tab.tabnew {
|
||||
font-size: 0.78em; padding: 6px 10px; letter-spacing: 0.06em;
|
||||
max-width: 11ch; overflow: hidden; text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tab.tabnew { border-style: dashed; opacity: 0.85; }
|
||||
.tab.tabnew:hover { opacity: 1; }
|
||||
|
||||
/* En pantalla ancha el mapping se reparte: la previsualizacion grande a la
|
||||
izquierda (que es donde se trabaja) y las capas con sus propiedades a la
|
||||
derecha, sin tener que bajar y subir todo el rato. */
|
||||
@media (min-width: 1000px) {
|
||||
body[data-view="mapping"] main {
|
||||
display: grid; width: 96%; max-width: 1700px;
|
||||
grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
|
||||
grid-template-areas: "previa capas" "previa props" "previa .";
|
||||
align-items: start; align-content: start; gap: 16px;
|
||||
}
|
||||
body[data-view="mapping"] #card-mapping { grid-area: previa; }
|
||||
body[data-view="mapping"] #card-capas { grid-area: capas; }
|
||||
body[data-view="mapping"] #card-propiedades { grid-area: props; }
|
||||
/* La previsualizacion manda: que ocupe todo el alto util disponible */
|
||||
body[data-view="mapping"] #map-preview { aspect-ratio: 16 / 9; }
|
||||
|
||||
/* La vista de una capa: previa a la izquierda, sus ajustes a la derecha */
|
||||
body[data-view="capa"] main {
|
||||
display: grid; width: 96%; max-width: 1700px;
|
||||
grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
|
||||
grid-template-areas: "previa props";
|
||||
align-items: start; align-content: start; gap: 16px;
|
||||
}
|
||||
body[data-view="capa"] #card-mapping { grid-area: previa; }
|
||||
body[data-view="capa"] #card-propiedades { grid-area: props; }
|
||||
body[data-view="capa"] #map-preview { aspect-ratio: 16 / 9; }
|
||||
}
|
||||
|
||||
/* --- Tarjetas --- */
|
||||
.card {
|
||||
background: var(--card); border: 1px solid var(--line);
|
||||
|
|
@ -90,11 +180,12 @@ main {
|
|||
}
|
||||
.card.center { align-items: center; }
|
||||
|
||||
/* Cabecera de tarjeta: titulo centrado, boton de info a la derecha */
|
||||
/* Cabecera de tarjeta: titulo centrado, boton de info a la derecha.
|
||||
El hueco lateral evita que un titulo largo se meta debajo del boton. */
|
||||
.cardhead {
|
||||
position: relative; width: 100%;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
min-height: 30px;
|
||||
min-height: 30px; padding: 0 34px;
|
||||
}
|
||||
/* Titulo de cada tarjeta: mas grande y en la fuente Xirod */
|
||||
.cardhead .label {
|
||||
|
|
@ -108,8 +199,12 @@ main {
|
|||
.hint { color: var(--dim); font-size: 12px; line-height: 1.45; }
|
||||
|
||||
.row { display: flex; align-items: center; justify-content: space-between;
|
||||
gap: 10px; }
|
||||
gap: 10px; flex-wrap: wrap; }
|
||||
.row .cmd { flex: 1; }
|
||||
/* En una fila de etiqueta + desplegable, el desplegable no baja de un ancho
|
||||
usable: si no cabe, la fila parte en dos lineas en vez de estrujarlo. */
|
||||
.row .label { flex: 1 1 auto; }
|
||||
.row select.inline { flex: 0 1 auto; min-width: 148px; max-width: 100%; }
|
||||
|
||||
/* --- Boton de informacion (circular naranja, esquina de la tarjeta) --- */
|
||||
.info {
|
||||
|
|
@ -139,11 +234,18 @@ main {
|
|||
display: flex; flex-wrap: wrap; gap: 12px; justify-content: center;
|
||||
}
|
||||
.engine {
|
||||
width: 96px; height: 96px; border-radius: 50%;
|
||||
width: 96px; aspect-ratio: 1 / 1; border-radius: 50%;
|
||||
display: flex; flex-direction: column; align-items: center;
|
||||
justify-content: center; gap: 2px; cursor: pointer;
|
||||
background: var(--card); border: 3px solid var(--line); color: var(--txt);
|
||||
}
|
||||
/* En movil, algo mas pequenos para que entren TRES por fila: con 96 px se
|
||||
quedaban en un 2+2+1 descuadrado (flex parte la linea antes de encoger). */
|
||||
@media (max-width: 560px) {
|
||||
.engines { gap: 10px; }
|
||||
.engine { width: 86px; }
|
||||
.engine strong { font-size: 12px; }
|
||||
}
|
||||
.engine strong { font-size: 13px; }
|
||||
.engine small { font-size: 9px; color: var(--dim); }
|
||||
.engine.active {
|
||||
|
|
@ -222,15 +324,14 @@ input[type=range] { width: 100%; accent-color: var(--green); height: 30px; }
|
|||
font-size: 12px; font-family: monospace; padding: 4px 0 8px;
|
||||
}
|
||||
|
||||
/* --- Banda de avisos --- */
|
||||
/* --- Banda de avisos (dentro de la barra superior fija) --- */
|
||||
.notif {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding: 12px 16px; font-size: 14px; font-weight: 600;
|
||||
position: sticky; top: 66px; z-index: 9;
|
||||
}
|
||||
.notif.info { background: var(--green); color: var(--ink); }
|
||||
.notif.warn { background: var(--orange); color: var(--ink); }
|
||||
.notif.error { background: var(--red); color: #fff; }
|
||||
.notif.lv-info { background: var(--green); color: var(--ink); }
|
||||
.notif.lv-warn { background: var(--orange); color: var(--ink); }
|
||||
.notif.lv-error { background: var(--red); color: #fff; }
|
||||
.notif span { flex: 1; }
|
||||
.notif button {
|
||||
background: transparent; border: none; color: inherit;
|
||||
|
|
@ -257,6 +358,70 @@ input[type=range] { width: 100%; accent-color: var(--green); height: 30px; }
|
|||
}
|
||||
.modal-box p { color: var(--txt); font-size: 14px; line-height: 1.5; }
|
||||
|
||||
/* --- Bloques agrupados dentro de una tarjeta ---
|
||||
Un grupo de controles que aparece o desaparece junto (por ejemplo los de
|
||||
la camara o los del fondo Butter en el mezclador). */
|
||||
.stack { display: flex; flex-direction: column; gap: 12px; }
|
||||
|
||||
/* Controles que ahora mismo no pintan nada: siguen visibles pero apagados,
|
||||
asi se ve que existen sin que despisten. */
|
||||
.dim { opacity: 0.42; }
|
||||
|
||||
/* Resumen del mezclador: la linea que dice que va a salir por el proyector */
|
||||
.hint.resumen {
|
||||
border-left: 3px solid var(--orange); padding: 6px 0 6px 10px;
|
||||
color: var(--txt); font-size: 13px;
|
||||
}
|
||||
|
||||
/* --- Previsualizacion del mapping --- */
|
||||
#map-preview {
|
||||
width: 100%; aspect-ratio: 16 / 9; display: block; margin: 6px 0;
|
||||
background: #0a0a0a; border: 1px solid var(--line); border-radius: 8px;
|
||||
touch-action: none; cursor: crosshair;
|
||||
}
|
||||
|
||||
/* --- Lista de capas del mapping ---
|
||||
Una fila por capa: nombre + fuente a la izquierda, botones a la derecha.
|
||||
La fila entera selecciona; los botones no la seleccionan. */
|
||||
#map-list { display: flex; flex-direction: column; gap: 8px; }
|
||||
.capa {
|
||||
display: flex; align-items: center; gap: 8px; cursor: pointer;
|
||||
padding: 9px 10px; border-radius: 11px;
|
||||
background: #161d10; border: 2px solid var(--line);
|
||||
}
|
||||
.capa.sel { border-color: var(--orange); box-shadow: 0 0 12px rgba(255,122,0,0.3); }
|
||||
.capa.oculta { opacity: 0.45; }
|
||||
.capa .txt { flex: 1; min-width: 0; }
|
||||
.capa .nom {
|
||||
display: block; color: var(--txt); font-weight: 700; font-size: 14px;
|
||||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||||
}
|
||||
.capa .src {
|
||||
display: block; color: var(--dim); font-size: 11px;
|
||||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||||
}
|
||||
.capa.mascara .nom { color: #ff6b6b; }
|
||||
.capa button {
|
||||
flex: 0 0 auto; width: 34px; height: 34px; border-radius: 9px; cursor: pointer;
|
||||
background: #0d120c; border: 1px solid var(--line); color: var(--txt);
|
||||
font-size: 14px; font-weight: 700; line-height: 1; padding: 0;
|
||||
}
|
||||
.capa button:disabled { opacity: 0.3; }
|
||||
.capa .del { color: var(--red); }
|
||||
|
||||
/* Malla: los +/- son botones pequenos y van juntos, no barras a lo ancho */
|
||||
.grupo { display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto; }
|
||||
#map-sub-dec, #map-sub-inc {
|
||||
flex: 0 0 auto; width: 46px; padding: 10px 0; font-size: 17px;
|
||||
}
|
||||
#map-sub-val { min-width: 40px; text-align: center; }
|
||||
|
||||
/* Campo de texto (nombre de la capa) */
|
||||
.txt[type="text"] {
|
||||
flex: 1; padding: 10px; border-radius: 10px; font-size: 14px;
|
||||
background: #161d10; color: var(--txt); border: 1px solid var(--line);
|
||||
}
|
||||
|
||||
/* Favoritos de projectM: lista de visuales para pinchar en directo */
|
||||
#pm-fav-list {
|
||||
display: flex; flex-direction: column; gap: 8px;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue