Merge adjacent event rows across tracks, batch independent chain triggers
This commit is contained in:
@@ -201,7 +201,26 @@ function render(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addRow(cells, rowClass) {
|
function addRow(cells, rowClass) {
|
||||||
rows.push({ cells, rowClass: rowClass || '' });
|
rowClass = rowClass || '';
|
||||||
|
if (rows.length > 0) {
|
||||||
|
const last = rows[rows.length - 1];
|
||||||
|
if (last.rowClass === rowClass) {
|
||||||
|
let canMerge = true;
|
||||||
|
for (let i = 0; i < cells.length; i++) {
|
||||||
|
if ((cells[i].event || cells[i].cueLabel) && (last.cells[i].event || last.cells[i].cueLabel)) {
|
||||||
|
canMerge = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (canMerge) {
|
||||||
|
for (let i = 0; i < cells.length; i++) {
|
||||||
|
if (cells[i].event || cells[i].cueLabel) last.cells[i] = cells[i];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rows.push({ cells, rowClass });
|
||||||
}
|
}
|
||||||
|
|
||||||
function flush() {
|
function flush() {
|
||||||
@@ -243,42 +262,57 @@ function render(data) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function processTrigger(trigger) {
|
function processChainBatch(chains) {
|
||||||
const src = trigger.source;
|
flush();
|
||||||
if (src.signal === 'START') return;
|
const chainEnds = [];
|
||||||
const isCue = src.signal === 'GO';
|
for (const trigger of chains) {
|
||||||
|
const src = trigger.source.block;
|
||||||
if (isChain(trigger)) {
|
const tid = blockTrack(src);
|
||||||
const tid = blockTrack(src.block);
|
if (active.get(tid) === src || pendingEnds.has(src)) {
|
||||||
const tgt = trigger.targets[0].block;
|
pendingEnds.delete(src);
|
||||||
const sourceHandled = active.get(tid) !== src.block && !pendingEnds.has(src.block);
|
chainEnds.push({ block: src, track: tid });
|
||||||
if (!sourceHandled) flush();
|
|
||||||
if (active.get(tid) === src.block || pendingEnds.has(src.block)) {
|
|
||||||
pendingEnds.delete(src.block);
|
|
||||||
const endCells = trackIds.map(t =>
|
|
||||||
t === tid ? { blockId: src.block, segment: 'end', event: 'END' } : mid(t)
|
|
||||||
);
|
|
||||||
addRow(endCells);
|
|
||||||
active.delete(tid);
|
active.delete(tid);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (chainEnds.length > 0) {
|
||||||
|
const endCells = trackIds.map(t => {
|
||||||
|
const e = chainEnds.find(ce => ce.track === t);
|
||||||
|
return e ? { blockId: e.block, segment: 'end', event: 'END' } : mid(t);
|
||||||
|
});
|
||||||
|
addRow(endCells);
|
||||||
|
}
|
||||||
|
const chainStarts = new Map();
|
||||||
|
const combinedTargets = new Map();
|
||||||
|
for (const trigger of chains) {
|
||||||
|
const tgt = trigger.targets[0].block;
|
||||||
|
const tid = blockTrack(tgt);
|
||||||
active.set(tid, tgt);
|
active.set(tid, tgt);
|
||||||
const targetMap = new Map();
|
const targetMap = new Map();
|
||||||
const extras = startSignalMap.get(tgt);
|
const extras = startSignalMap.get(tgt);
|
||||||
if (extras) extras.forEach(et => targetMap.set(et.block, et.hook));
|
if (extras) extras.forEach(et => targetMap.set(et.block, et.hook));
|
||||||
expandTargets(targetMap);
|
expandTargets(targetMap);
|
||||||
const hasTargets = targetMap.size > 0;
|
chainStarts.set(tid, { blockId: tgt, hasTargets: targetMap.size > 0 });
|
||||||
const directEnds = [];
|
for (const [bid, hook] of targetMap) {
|
||||||
noTitleAfter.add(rows.length - 1);
|
if (!combinedTargets.has(bid)) combinedTargets.set(bid, hook);
|
||||||
const startCells = trackIds.map(t => {
|
}
|
||||||
if (t === tid) return { blockId: tgt, segment: 'start', event: 'START', isSignal: hasTargets };
|
|
||||||
const cell = applyTargets(targetMap, t, false);
|
|
||||||
if (cell) { if (cell.directEnd) { directEnds.push(cell.blockId); delete cell.directEnd; } return cell; }
|
|
||||||
return mid(t);
|
|
||||||
});
|
|
||||||
addRow(startCells, hasTargets ? 'sig-row' : '');
|
|
||||||
directEnds.forEach(bid => active.delete(blockTrack(bid)));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
const hasAnyTargets = [...chainStarts.values()].some(cs => cs.hasTargets);
|
||||||
|
noTitleAfter.add(rows.length - 1);
|
||||||
|
const directEnds = [];
|
||||||
|
const startCells = trackIds.map(t => {
|
||||||
|
const cs = chainStarts.get(t);
|
||||||
|
if (cs) return { blockId: cs.blockId, segment: 'start', event: 'START', isSignal: cs.hasTargets };
|
||||||
|
const cell = applyTargets(combinedTargets, t, false);
|
||||||
|
if (cell) { if (cell.directEnd) { directEnds.push(cell.blockId); delete cell.directEnd; } return cell; }
|
||||||
|
return mid(t);
|
||||||
|
});
|
||||||
|
addRow(startCells, hasAnyTargets ? 'sig-row' : '');
|
||||||
|
directEnds.forEach(bid => active.delete(blockTrack(bid)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function processTrigger(trigger) {
|
||||||
|
const src = trigger.source;
|
||||||
|
const isCue = src.signal === 'GO';
|
||||||
|
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
@@ -318,7 +352,35 @@ function render(data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data.triggers.forEach(t => processTrigger(t));
|
let triggerIdx = 0;
|
||||||
|
while (triggerIdx < data.triggers.length) {
|
||||||
|
const t = data.triggers[triggerIdx];
|
||||||
|
if (t.source.signal === 'START') { triggerIdx++; continue; }
|
||||||
|
if (isChain(t)) {
|
||||||
|
if (startSignalMap.has(t.targets[0].block)) {
|
||||||
|
processChainBatch([t]);
|
||||||
|
triggerIdx++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const batch = [t];
|
||||||
|
const batchTracks = new Set([blockTrack(t.source.block)]);
|
||||||
|
let j = triggerIdx + 1;
|
||||||
|
while (j < data.triggers.length) {
|
||||||
|
if (data.triggers[j].source.signal === 'START') { j++; continue; }
|
||||||
|
if (!isChain(data.triggers[j])) break;
|
||||||
|
if (batchTracks.has(blockTrack(data.triggers[j].source.block))) break;
|
||||||
|
if (startSignalMap.has(data.triggers[j].targets[0].block)) break;
|
||||||
|
batchTracks.add(blockTrack(data.triggers[j].source.block));
|
||||||
|
batch.push(data.triggers[j]);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
processChainBatch(batch);
|
||||||
|
triggerIdx = j;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
processTrigger(t);
|
||||||
|
triggerIdx++;
|
||||||
|
}
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
const stillActive = [];
|
const stillActive = [];
|
||||||
|
|||||||
Reference in New Issue
Block a user