From c90275d664a21abe6d93de7715b85a314054a149 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Tue, 27 Jan 2026 16:08:55 -0800 Subject: [PATCH] Improve Art-Net hover display with device correspondence Co-Authored-By: Claude Opus 4.5 --- static/index.html | 65 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/static/index.html b/static/index.html index 908b23e..7c257d6 100644 --- a/static/index.html +++ b/static/index.html @@ -1345,13 +1345,15 @@ if (artnetInfo && artnetInfo.isOut) { const outEl = document.createElement('div'); outEl.className = 'artnet-info out-info'; + const firstOut = artnetInfo.outputs[0]; + const outLabel = firstOut.firstTarget || firstOut.display; const outMore = artnetInfo.outputs.length > 1 ? ', ...' : ''; - outEl.innerHTML = ' ' + artnetInfo.outputs[0] + outMore; + outEl.innerHTML = ' ' + outLabel + outMore; const detailWrapper = document.createElement('div'); detailWrapper.className = 'artnet-detail-wrapper'; const detail = document.createElement('div'); detail.className = 'artnet-detail'; - buildClickableList(detail, artnetInfo.outputs, '←', (l, v) => l + ' ' + v); + buildClickableList(detail, artnetInfo.outputs.map(o => o.display), '←', (l, v) => l + ' ' + v); detailWrapper.appendChild(detail); outEl.appendChild(detailWrapper); div.appendChild(outEl); @@ -1360,13 +1362,15 @@ if (artnetInfo && artnetInfo.isIn) { const inEl = document.createElement('div'); inEl.className = 'artnet-info in-info'; + const firstIn = artnetInfo.inputs[0]; + const inLabel = firstIn.firstTarget || firstIn.display; const inMore = artnetInfo.inputs.length > 1 ? ', ...' : ''; - inEl.innerHTML = ' ' + artnetInfo.inputs[0] + inMore; + inEl.innerHTML = ' ' + inLabel + inMore; const detailWrapper = document.createElement('div'); detailWrapper.className = 'artnet-detail-wrapper'; const detail = document.createElement('div'); detail.className = 'artnet-detail'; - buildClickableList(detail, artnetInfo.inputs, '→', (l, v) => l + ' ' + v); + buildClickableList(detail, artnetInfo.inputs.map(i => i.display), '→', (l, v) => l + ' ' + v); detailWrapper.appendChild(detail); inEl.appendChild(detailWrapper); div.appendChild(inEl); @@ -1749,19 +1753,54 @@ const artnetData = data.artnet_nodes || []; const artnetNodes = new Map(); + const formatUniverse = (u) => { + const net = (u >> 8) & 0x7f; + const subnet = (u >> 4) & 0x0f; + const universe = u & 0x0f; + return net + ':' + subnet + ':' + universe + ' (' + u + ')'; + }; + + const universeInputs = new Map(); + const universeOutputs = new Map(); + + artnetData.forEach(an => { + const name = getShortLabel(an.node); + (an.inputs || []).forEach(u => { + if (!universeInputs.has(u)) universeInputs.set(u, []); + universeInputs.get(u).push(name); + }); + (an.outputs || []).forEach(u => { + if (!universeOutputs.has(u)) universeOutputs.set(u, []); + universeOutputs.get(u).push(name); + }); + }); + + const collapseNames = (names) => { + const counts = {}; + names.forEach(n => counts[n] = (counts[n] || 0) + 1); + return Object.entries(counts).map(([name, count]) => count > 1 ? name + ' x' + count : name); + }; + artnetData.forEach(an => { const nodeId = an.node?.typeid; if (!nodeId) return; - const formatUniverse = (u) => { - const net = (u >> 8) & 0x7f; - const subnet = (u >> 4) & 0x0f; - const universe = u & 0x0f; - return net + ':' + subnet + ':' + universe + ' (' + u + ')'; - }; - - const inputs = (an.inputs || []).slice().sort((a, b) => a - b).map(formatUniverse); - const outputs = (an.outputs || []).slice().sort((a, b) => a - b).map(formatUniverse); + const inputs = (an.inputs || []).slice().sort((a, b) => a - b).map(u => { + const sources = collapseNames(universeOutputs.get(u) || []); + const uniStr = formatUniverse(u); + if (sources.length > 0) { + return { display: sources[0] + ' [' + uniStr + ']', firstTarget: sources[0] }; + } + return { display: uniStr, firstTarget: null }; + }); + const outputs = (an.outputs || []).slice().sort((a, b) => a - b).map(u => { + const dests = collapseNames(universeInputs.get(u) || []); + const uniStr = formatUniverse(u); + if (dests.length > 0) { + return { display: dests[0] + ' [' + uniStr + ']', firstTarget: dests[0] }; + } + return { display: uniStr, firstTarget: null }; + }); artnetNodes.set(nodeId, { isOut: outputs.length > 0,