From 8aa41e2affced76415fee4fc904fcceae9be9f24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=27=C3=A9lectron=20rare?= <108685187+electron-rare@users.noreply.github.com> Date: Mon, 29 Jun 2026 15:28:57 +0200 Subject: [PATCH] feat(web): live mod-source meters --- web_realart/public/control/control.css | 6 ++++++ web_realart/public/control/js/voice-editor.js | 17 ++++++++++++++++- web_realart/test/colordefs-parse.test.mjs | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/web_realart/public/control/control.css b/web_realart/public/control/control.css index 07691b9..2436817 100644 --- a/web_realart/public/control/control.css +++ b/web_realart/public/control/control.css @@ -212,3 +212,9 @@ button.queued { animation: queued-blink 600ms ease-in-out infinite alternate; } .seq-cell.playhead { outline: 2px solid rgba(255,255,255,0.75); outline-offset: -1px; } .pr-cell.playhead { background: rgba(255,255,255,0.14); outline: 1px solid rgba(255,255,255,0.55); outline-offset: -1px; } .pr-cell.on.playhead { filter: brightness(1.45); outline: 1px solid #fff; outline-offset: -1px; } + +/* --- Mod-source live meters --- */ +.cd-meter { display:inline-block; width:42px; height:8px; border:1px solid #444; + border-radius:3px; vertical-align:middle; margin:0 4px; position:relative; background:#1b1b1b; } +.cd-meter::after { content:""; position:absolute; left:0; top:0; bottom:0; + width:calc(var(--v,0) * 100%); background:#1a8; border-radius:2px; } diff --git a/web_realart/public/control/js/voice-editor.js b/web_realart/public/control/js/voice-editor.js index 35ac636..87d1a1a 100644 --- a/web_realart/public/control/js/voice-editor.js +++ b/web_realart/public/control/js/voice-editor.js @@ -7,7 +7,7 @@ import { VOICE_CLASS, defaultStepMode, isMelodic, matVoiceMods, matVoicePoses, MOD_SOURCE_LABELS, MOD_TARGET_LABELS, POSE_EVENT_CHOICES, - parseVoiceMod, parseVoicePose, + parseVoiceMod, parseVoicePose, parseModValues, } from "./matrix-state.js"; // Per-voice step edit mode; initialised from defaultStepMode() on first expand. @@ -566,6 +566,21 @@ on("/matrix/voicepose", (args) => { } }); +let latestModValues = {}; +on("/matrix/modvalues", (args) => { + latestModValues = parseModValues(args); + updateMeters(); +}); +function updateMeters() { + if (expandedVoice < 0 || activeTab !== "modpose") return; + const meters = cdTabBodyEl ? cdTabBodyEl.querySelectorAll(".cd-meter") : []; + meters.forEach((m) => { + const v = latestModValues[m.dataset.src] || 0; + m.style.setProperty("--v", v.toFixed(3)); + m.title = `${m.dataset.src}: ${v.toFixed(2)}`; + }); +} + on("/matrix/stephead", (args) => { // Guard: only act when a voice is open and the STEPS tab is active. if (expandedVoice < 0 || !cdTabBodyEl || activeTab !== "steps") return; diff --git a/web_realart/test/colordefs-parse.test.mjs b/web_realart/test/colordefs-parse.test.mjs index c1238d0..42460bd 100644 --- a/web_realart/test/colordefs-parse.test.mjs +++ b/web_realart/test/colordefs-parse.test.mjs @@ -33,6 +33,7 @@ export let matVoiceMods=Array.from({length:22},()=>[]); export let matVoicePoses=Array.from({length:22},()=>[]); export function parseVoiceMod(args){ return {vi:0,list:[]}; } export function parseVoicePose(args){ return {vi:0,list:[]}; } +export function parseModValues(){ return {}; } export function saveMatState(){} export const VOICE_CLASS={}; export function defaultStepMode(){ return "drum"; }